Создание составных Javascript / HTML “виджетов”

То, что я хотел бы сделать, – это динамически создать блок автономного HTML с дополнительными свойствами.

Я не уверен, как это назвать, поскольку теперь «виджет» подразумевает, что это что-то вроде чуда или значка, чтобы надеть свой блог. Я говорю о многоразовом, настраиваемом, «составном» объекте JS / HTML (/ CSS).

Например, простой выбор даты.

document.body.appendChild(new DatePicker()); 

Будет генерировать

 
January .... 1 .... 2010 ....

И имел бы такие свойства, как

 var d = new DatePicker(); d.value = "2010-06-21"; d.name = "the_datepicker"; d.month = 5; d.month = "June"; d.day = 21; d.year = 2010; 

Как это можно сделать (легко)? Каковы наилучшие методы для этой ситуации?

Мне нравится подход MooTools к этому. Любой объект JavaScript может определить метод toElement и вы можете добавить этот объект в DOM с помощью оберток MooTools. Обертки будут запрашивать свойство toElement объекта, и если оно существует, то возвращаемое значение вызова toElement() будет добавлено в DOM. Для этого вам придется использовать обертки для добавления в DOM вместо непосредственного использования appendChild .

 function DatePicker(date) { this.date = date; } DatePicker.prototype.toElement = function() { // return a DOM representation of this object }; var picker = new DatePicker(); 

Вот несколько способов использования этого:

 // retrieve the DOM node directly document.body.appendChild(picker.toElement()); // use a wrapper to append, that queries toElement first // DOM is a function like jQuery, that wraps the given DOM // object with additional methods like append for querying toElement. DOM(document.body).append(picker); 

Конечно, вы всегда можете перезаписать собственный метод appendChild , однако я бы не рекомендовал этого.

Ради полноты, вот как вы это сделаете. Используйте закрытие, чтобы удержать исходный метод appendChild , и замените его новым методом, который сначала проверяет, был ли toElement определен, и извлекает представление элемента этого объекта, если это так. В противном случае добавьте переданный объект, как есть.

 (function(original) { Element.prototype.appendChild = function(child) { if('toElement' in child) { original.call(this, child.toElement()); } else { original.call(this, child); } } })(Element.prototype.appendChild); 

Добавьте объект в DOM, как в вашем примере:

 document.body.appendChild(new DatePicker()); 

Есть несколько различных вариантов с этим.

Вы могли бы «подclassифицировать» объект-элемент, но это было бы крайне неэффективно, поскольку Javascript притворился бы как можно меньшим Object-Oriented. (Кроме того, расширение объектов хоста – это yuck .)

Тем не менее, подход, который я бы принял, заключался бы в определении функции DatePicker classе DatePicker .

Этот метод теоретически будет использовать атрибуты DatePicker и использовать их для создания HTML.

И если вы сохраните этот HTML- DatePicker , хранящийся в DatePicker , у вас будет простой способ его обновить и получить доступ к его значению по мере необходимости в коде.

Возможно, вам захочется проверить knockout.composite – http://danderson00.blogspot.com.au/2012/08/introducing-knockoutcomposite.html