diff --git a/README.md b/README.md index 0ad4cea..a5e1258 100644 --- a/README.md +++ b/README.md @@ -155,6 +155,8 @@ These advanced config options are also available: * `expandBtnHTML` The HTML text used to generate a list item expand button (default `''`) * `collapseBtnHTML` The HTML text used to generate a list item collapse button (default `''`) * `includeContent` Enable or disable the content in output (default `false`) +* `listRenderer` The callback for customizing final list output (default `function(children, options) { ... }` - see defaults in code) +* `itemRenderer` The callback for customizing final item output (default `function(item_attrs, content, children, options) { ... }` - see defaults in code) * `json` JSON string used to dynamically generate a Nestable list. This is the same format as the `serialize()` output **Inspect the [Nestable Demo](http://ramonsmit.github.io/Nestable/) for guidance.** @@ -163,6 +165,7 @@ These advanced config options are also available: ### 6th October 2014 +* [zemistr] Created listRenderer and itemRenderer. Refactored build from JSON. * [zemistr] Added support for adding classes via input data. (```[{"id": 1, "content": "First item", "classes": ["dd-nochildren", "dd-nodrag", ...] }, ... ]```) ### 3th October 2014 diff --git a/bower.json b/bower.json index b2c51b8..754ebaf 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "nestable2", - "version": "1.1.1", + "version": "1.2.1", "homepage": "https://github.com/RamonSmit/Nestable", "authors": [ "Ramon Smit <@_RamonSmit>", diff --git a/index.html b/index.html index 99f7255..f784cdc 100644 --- a/index.html +++ b/index.html @@ -500,24 +500,24 @@

Nestable

"content": "Item 8" } ] - }, - { - "id": 9, - "content": "Item 9" - }, + } + ] + }, + { + "id": 9, + "content": "Item 9" + }, + { + "id": 10, + "content": "Item 10", + "children": [ { - "id": 10, - "content": "Item 10", + "id": 11, + "content": "Item 11", "children": [ { - "id": 11, - "content": "Item 11", - "children": [ - { - "id": 12, - "content": "Item 12" - } - ] + "id": 12, + "content": "Item 12" } ] } diff --git a/jquery.nestable.js b/jquery.nestable.js index c57d0c9..dc0b69a 100644 --- a/jquery.nestable.js +++ b/jquery.nestable.js @@ -54,7 +54,30 @@ fixedDepth: false, //fixed item's depth fixed: false, includeContent: false, - callback: function(l, e) {} + callback: function(l, e) {}, + listRenderer: function(children, options) { + var html = '<' + options.listNodeName + ' class="' + options.listClass + '">'; + html += children; + html += ''; + + return html; + }, + itemRenderer: function(item_attrs, content, children, options) { + var item_attrs_string = $.map(item_attrs, function(value, key) { + return ' ' + key + '="' + value + '"'; + }).join(' '); + + var html = '<' + options.itemNodeName + item_attrs_string + '>'; + html += '<' + options.handleNodeName + ' class="' + options.handleClass + '">'; + html += '<' + options.contentNodeName + ' class="' + options.contentClass + '">'; + html += content; + html += ''; + html += ''; + html += children; + html += ''; + + return html; + } }; function Plugin(element, options) { @@ -164,10 +187,6 @@ }, _build: function() { - var output = "<" + this.options.listNodeName + - " class='" + this.options.listClass + - "'>"; - function escapeHtml(text) { var map = { '&': '&', @@ -180,77 +199,84 @@ return text + "".replace(/[&<>"']/g, function(m) { return map[m]; }); } - function buildItem(item, options) { - var children = item.children; - var content = options.contentCallback(item); - var item_classes = {}; - var classes = item.classes || {}; + function filterClasses(classes) { + var new_classes = {}; - if(typeof classes == 'string') { - classes = [classes]; + for(var k in classes) { + // Remove duplicates + new_classes[classes[k]] = classes[k]; } - delete item.children; - delete item.classes; - delete item.content; + return new_classes; + } - for(var k in classes) { - // Remove duplicates - item_classes[classes[k]] = classes[k]; + function createClassesString(item, options) { + var classes = item.classes || {}; + + if(typeof classes == 'string') { + classes = [classes]; } + var item_classes = filterClasses(classes); item_classes[options.itemClass] = options.itemClass; // create class string - var classes_string = $.map(item_classes, function(val) { + return $.map(item_classes, function(val) { return val; }).join(' '); + } + + function createDataAttrs(attr) { + attr = $.extend({}, attr); + + delete attr.children; + delete attr.classes; + delete attr.content; - var html = "<" + options.itemNodeName + " class='" + classes_string + "'"; + var data_attrs = {}; - $.each(item, function(key, value) { + $.each(attr, function(key, value) { if(typeof value == 'object') { value = JSON.stringify(value); } - html += " data-" + key + "='" + escapeHtml(value) + "'"; + data_attrs["data-" + key] = escapeHtml(value); }); - html += ">"; - html += "<" + options.handleNodeName + " class='" + options.handleClass + "'>"; - html += "<" + options.contentNodeName + " class='" + options.contentClass + "'>"; - html += content; - html += ""; + return data_attrs; + } - if(children) { - html += "<" + options.listNodeName + " class='" + options.listClass + "'>"; + function buildList(items, options) { + if(!items) { + return ''; + } - $.each(children, function(index, sub) { - html += buildItem(sub, options); - }); + var children = ''; - html += ""; - } + $.each(items, function(index, sub) { + children += buildItem(sub, options); + }); - html += ""; + return options.listRenderer(children, options); + } + + function buildItem(item, options) { + var item_attrs = createDataAttrs(item); + item_attrs["class"] = createClassesString(item, options); + + var content = options.contentCallback(item); + var children = buildList(item.children, options); - return html; + return options.itemRenderer(item_attrs, content, children, options); } - var options = this.options; var json = this.options.json; if(typeof json == 'string') { json = JSON.parse(json); } - $.each(json, function(index, item) { - output += buildItem(item, options); - }); - - output += ""; - - $(this.el).html(output); + $(this.el).html(buildList(json, this.options)); }, serialize: function() {