Я хочу сделать следующее:

  1. объявить применимые виджеты, например. вот так: $.fn.myWidget = function(options) { ... }
  2. определить в html, какой виджет применить к элементу: <div widget="myWidget">some text</div>

В случае, когда я не вставляю код динамически, реализовать такую ​​вещь почти тривиально:

$(function() {
  $('*[widget]').each(function() { $(this)[$(this).attr('widget')]() })
})

Но когда код вставляется динамически (например, из AJAX), нам также нужно пройти этот новый код. Итак, есть два вопроса:

  1. Есть ли плагин, библиотека или что-то, что решает мою более широкую проблему (например, взять имя виджета из атрибута html и инициализировать виджет для этого элемента)?
  2. Есть ли какая-то функциональность, которая позволяет обрабатывать (перехватывать) случаи, когда jQuery динамически вставляет html-элементы (используя .html(), .prepend(), .load() и т. д.)?

обновление: подробнее

Частично решить проблему можно, используя следующий подход:

$.fn.applyWidgets = function() {
  this.each(function() {
    var $e = $(element);
    var widget = $e.attr('widget');
    if(widget) $e[widget]();
  });
}

$.fn.htmlWithWidgets = function(html) { 
  this.html($(html).applyWidgets());
}

А затем используйте $(selector).htmlWithWidgets(html) вместо $(selector).html(html)

Тем не менее было бы интересно научиться перехватывать html() и подобные вызовы и применять подход неявно, "изнутри".

0
Alexey 28 Дек 2011 в 00:22
Томалак, не могли бы вы уточнить, что не так с моими тегами?
 – 
Alexey
28 Дек 2011 в 01:04
Ничего такого. Но теги идут в тегах; не повторяйте их в заголовке, пожалуйста.
 – 
Lightness Races in Orbit
28 Дек 2011 в 01:05
Итак, идея состоит в том, что тег обобщает контекст, а заголовок обобщает содержание. Правильно?
 – 
Alexey
28 Дек 2011 в 01:12
Да, точно! :) Сам бы не сказал лучше.
 – 
Lightness Races in Orbit
28 Дек 2011 в 01:34
Похоже, что вы ищете "элемент управления" на стороне сервера - что-то вроде элементов управления ASP.NET.
 – 
Ilia G
28 Дек 2011 в 03:54

1 ответ

Наконец, я получаю следующее решение:

  var _widget_bindings = {}

  // registers css_class and associates with widget_initializer callback
  function bind_widget(css_class, widget_initializer) {
    if (jQuery.fn[css_class]) throw "widget with name "+css_class+"already defined";
    _widget_bindings[css_class] = widget_initializer;
    jQuery.fn[css_class] = widget_initializer;
  }

  // for each element in set takes DOM subtree and for each element in the subtree with registered css_class
  // invokes corresponding widget_initializer
  jQuery.fn.init_widgets = function() {
    this.find('*[class]').andSelf().each(function() {
      if (!this.className) return;
      var classes = this.className.split(/\s+/);
      for (var i = 0, l = classes.length; i < l; i++) {
        var css_class = classes[i];
        if (css_class && _widget_bindings.hasOwnProperty(css_class))
          _widget_bindings[css_class].apply(jQuery(this));
      }
    })
    return this;
  }

  // invokes a method (can be .html(), .append(), .prepend(), .before(), .after()) by given method_name
  // and initializes widgets for newly created elements
  jQuery.fn.with_widgets = function(method_name, elements) {
    var j_elements = jQuery(elements);
    this[method_name](j_elements);
    j_elements.init_widgets();
    return this;
  }

  jQuery(document).ready(function() { (document.body).init_widgets() })
0
Alexey 7 Янв 2012 в 00:06