|
1 | 1 | /**
|
2 |
| - * selectize.js (v0.12.1) |
| 2 | + * selectize.js (v) |
3 | 3 | * Copyright (c) 2013–2015 Brian Reavis & contributors
|
4 | 4 | *
|
5 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
|
|
444 | 444 | update();
|
445 | 445 | };
|
446 | 446 |
|
| 447 | + var domToString = function(d) { |
| 448 | + var tmp = document.createElement('div'); |
| 449 | + |
| 450 | + tmp.appendChild(d.cloneNode(true)); |
| 451 | + |
| 452 | + return tmp.innerHTML; |
| 453 | + }; |
| 454 | + |
| 455 | + |
447 | 456 | var Selectize = function($input, settings) {
|
448 | 457 | var key, i, n, dir, input, self = this;
|
449 | 458 | input = $input[0];
|
|
830 | 839 | }
|
831 | 840 | },
|
832 | 841 |
|
| 842 | + /** |
| 843 | + * Trigger Native browser event. |
| 844 | + */ |
| 845 | + triggerNativeEvent: function(el, eventName){ |
| 846 | + if (el.fireEvent) { // < IE9 |
| 847 | + (el.fireEvent('on' + eventName)); |
| 848 | + } else { |
| 849 | + var evt = document.createEvent('Events'); |
| 850 | + evt.initEvent(eventName, true, false); |
| 851 | + el.dispatchEvent(evt); |
| 852 | + } |
| 853 | + }, |
| 854 | + |
833 | 855 | /**
|
834 | 856 | * Triggered when the value of the control has been changed.
|
835 | 857 | * This should propagate the event to the original DOM
|
836 | 858 | * input / select element.
|
837 | 859 | */
|
838 | 860 | onChange: function() {
|
839 | 861 | this.$input.trigger('change');
|
| 862 | + this.triggerNativeEvent(this.$input.get(0), 'change'); |
840 | 863 | },
|
841 | 864 |
|
842 | 865 | /**
|
|
1506 | 1529 | optgroup = '';
|
1507 | 1530 | }
|
1508 | 1531 | if (!groups.hasOwnProperty(optgroup)) {
|
1509 |
| - groups[optgroup] = []; |
| 1532 | + groups[optgroup] = document.createDocumentFragment(); |
1510 | 1533 | groups_order.push(optgroup);
|
1511 | 1534 | }
|
1512 |
| - groups[optgroup].push(option_html); |
| 1535 | + groups[optgroup].appendChild(option_html); |
1513 | 1536 | }
|
1514 | 1537 | }
|
1515 | 1538 |
|
|
1523 | 1546 | }
|
1524 | 1547 |
|
1525 | 1548 | // render optgroup headers & join groups
|
1526 |
| - html = []; |
| 1549 | + html = document.createDocumentFragment(); |
1527 | 1550 | for (i = 0, n = groups_order.length; i < n; i++) {
|
1528 | 1551 | optgroup = groups_order[i];
|
1529 |
| - if (self.optgroups.hasOwnProperty(optgroup) && groups[optgroup].length) { |
| 1552 | + if (self.optgroups.hasOwnProperty(optgroup) && groups[optgroup].childNodes.length) { |
1530 | 1553 | // render the optgroup header and options within it,
|
1531 | 1554 | // then pass it to the wrapper template
|
1532 |
| - html_children = self.render('optgroup_header', self.optgroups[optgroup]) || ''; |
1533 |
| - html_children += groups[optgroup].join(''); |
1534 |
| - html.push(self.render('optgroup', $.extend({}, self.optgroups[optgroup], { |
1535 |
| - html: html_children |
| 1555 | + html_children = document.createDocumentFragment(); |
| 1556 | + html_children.appendChild(self.render('optgroup_header', self.optgroups[optgroup])); |
| 1557 | + html_children.appendChild(groups[optgroup]); |
| 1558 | + |
| 1559 | + html.appendChild(self.render('optgroup', $.extend({}, self.optgroups[optgroup], { |
| 1560 | + html: domToString(html_children), |
| 1561 | + dom: html_children |
1536 | 1562 | })));
|
1537 | 1563 | } else {
|
1538 |
| - html.push(groups[optgroup].join('')); |
| 1564 | + html.appendChild(groups[optgroup]); |
1539 | 1565 | }
|
1540 | 1566 | }
|
1541 | 1567 |
|
1542 |
| - $dropdown_content.html(html.join('')); |
| 1568 | + $dropdown_content.html(html); |
1543 | 1569 |
|
1544 | 1570 | // highlight matching terms inline
|
1545 | 1571 | if (self.settings.highlight && results.query.length && results.tokens.length) {
|
|
2490 | 2516 | }
|
2491 | 2517 |
|
2492 | 2518 | // render markup
|
2493 |
| - html = self.settings.render[templateName].apply(this, [data, escape_html]); |
| 2519 | + html = $(self.settings.render[templateName].apply(this, [data, escape_html])); |
2494 | 2520 |
|
2495 | 2521 | // add mandatory attributes
|
2496 | 2522 | if (templateName === 'option' || templateName === 'option_create') {
|
2497 |
| - html = html.replace(regex_tag, '<$1 data-selectable'); |
| 2523 | + html.attr('data-selectable', ''); |
2498 | 2524 | }
|
2499 |
| - if (templateName === 'optgroup') { |
| 2525 | + else if (templateName === 'optgroup') { |
2500 | 2526 | id = data[self.settings.optgroupValueField] || '';
|
2501 |
| - html = html.replace(regex_tag, '<$1 data-group="' + escape_replace(escape_html(id)) + '"'); |
| 2527 | + html.attr('data-group', id); |
2502 | 2528 | }
|
2503 | 2529 | if (templateName === 'option' || templateName === 'item') {
|
2504 |
| - html = html.replace(regex_tag, '<$1 data-value="' + escape_replace(escape_html(value || '')) + '"'); |
| 2530 | + html.attr('data-value', value || ''); |
2505 | 2531 | }
|
2506 | 2532 |
|
2507 | 2533 | // update cache
|
2508 | 2534 | if (cache) {
|
2509 |
| - self.renderCache[templateName][value] = html; |
| 2535 | + self.renderCache[templateName][value] = html[0]; |
2510 | 2536 | }
|
2511 | 2537 |
|
2512 |
| - return html; |
| 2538 | + return html[0]; |
2513 | 2539 | },
|
2514 | 2540 |
|
2515 | 2541 | /**
|
|
2971 | 2997 | });
|
2972 | 2998 |
|
2973 | 2999 | Selectize.define('remove_button', function(options) {
|
2974 |
| - if (this.settings.mode === 'single') return; |
2975 |
| - |
2976 | 3000 | options = $.extend({
|
2977 |
| - label : '×', |
2978 |
| - title : 'Remove', |
2979 |
| - className : 'remove', |
2980 |
| - append : true |
2981 |
| - }, options); |
| 3001 | + label : '×', |
| 3002 | + title : 'Remove', |
| 3003 | + className : 'remove', |
| 3004 | + append : true |
| 3005 | + }, options); |
| 3006 | + |
| 3007 | + var singleClose = function(thisRef, options) { |
| 3008 | + |
| 3009 | + options.className = 'remove-single'; |
| 3010 | + |
| 3011 | + var self = thisRef; |
| 3012 | + var html = '<a href="javascript:void(0)" class="' + options.className + '" tabindex="-1" title="' + escape_html(options.title) + '">' + options.label + '</a>'; |
| 3013 | + |
| 3014 | + /** |
| 3015 | + * Appends an element as a child (with raw HTML). |
| 3016 | + * |
| 3017 | + * @param {string} html_container |
| 3018 | + * @param {string} html_element |
| 3019 | + * @return {string} |
| 3020 | + */ |
| 3021 | + var append = function(html_container, html_element) { |
| 3022 | + return html_container + html_element; |
| 3023 | + }; |
| 3024 | + |
| 3025 | + thisRef.setup = (function() { |
| 3026 | + var original = self.setup; |
| 3027 | + return function() { |
| 3028 | + // override the item rendering method to add the button to each |
| 3029 | + if (options.append) { |
| 3030 | + var id = $(self.$input.context).attr('id'); |
| 3031 | + var selectizer = $('#'+id); |
| 3032 | + |
| 3033 | + var render_item = self.settings.render.item; |
| 3034 | + self.settings.render.item = function(data) { |
| 3035 | + return append(render_item.apply(thisRef, arguments), html); |
| 3036 | + }; |
| 3037 | + } |
2982 | 3038 |
|
2983 |
| - var self = this; |
2984 |
| - var html = '<a href="javascript:void(0)" class="' + options.className + '" tabindex="-1" title="' + escape_html(options.title) + '">' + options.label + '</a>'; |
| 3039 | + original.apply(thisRef, arguments); |
2985 | 3040 |
|
2986 |
| - /** |
2987 |
| - * Appends an element as a child (with raw HTML). |
2988 |
| - * |
2989 |
| - * @param {string} html_container |
2990 |
| - * @param {string} html_element |
2991 |
| - * @return {string} |
2992 |
| - */ |
2993 |
| - var append = function(html_container, html_element) { |
2994 |
| - var pos = html_container.search(/(<\/[^>]+>\s*)$/); |
2995 |
| - return html_container.substring(0, pos) + html_element + html_container.substring(pos); |
2996 |
| - }; |
| 3041 | + // add event listener |
| 3042 | + thisRef.$control.on('click', '.' + options.className, function(e) { |
| 3043 | + e.preventDefault(); |
| 3044 | + if (self.isLocked) return; |
| 3045 | + |
| 3046 | + self.clear(); |
| 3047 | + }); |
2997 | 3048 |
|
2998 |
| - this.setup = (function() { |
2999 |
| - var original = self.setup; |
3000 |
| - return function() { |
3001 |
| - // override the item rendering method to add the button to each |
3002 |
| - if (options.append) { |
3003 |
| - var render_item = self.settings.render.item; |
3004 |
| - self.settings.render.item = function(data) { |
3005 |
| - return append(render_item.apply(this, arguments), html); |
3006 | 3049 | };
|
3007 |
| - } |
| 3050 | + })(); |
| 3051 | + }; |
3008 | 3052 |
|
3009 |
| - original.apply(this, arguments); |
| 3053 | + var multiClose = function(thisRef, options) { |
| 3054 | + |
| 3055 | + var self = thisRef; |
| 3056 | + var html = '<a href="javascript:void(0)" class="' + options.className + '" tabindex="-1" title="' + escape_html(options.title) + '">' + options.label + '</a>'; |
| 3057 | + |
| 3058 | + /** |
| 3059 | + * Appends an element as a child (with raw HTML). |
| 3060 | + * |
| 3061 | + * @param {string} html_container |
| 3062 | + * @param {string} html_element |
| 3063 | + * @return {string} |
| 3064 | + */ |
| 3065 | + var append = function(html_container, html_element) { |
| 3066 | + var pos = html_container.search(/(<\/[^>]+>\s*)$/); |
| 3067 | + return html_container.substring(0, pos) + html_element + html_container.substring(pos); |
| 3068 | + }; |
| 3069 | + |
| 3070 | + thisRef.setup = (function() { |
| 3071 | + var original = self.setup; |
| 3072 | + return function() { |
| 3073 | + // override the item rendering method to add the button to each |
| 3074 | + if (options.append) { |
| 3075 | + var render_item = self.settings.render.item; |
| 3076 | + self.settings.render.item = function(data) { |
| 3077 | + return append(render_item.apply(thisRef, arguments), html); |
| 3078 | + }; |
| 3079 | + } |
3010 | 3080 |
|
3011 |
| - // add event listener |
3012 |
| - this.$control.on('click', '.' + options.className, function(e) { |
3013 |
| - e.preventDefault(); |
3014 |
| - if (self.isLocked) return; |
| 3081 | + original.apply(thisRef, arguments); |
3015 | 3082 |
|
3016 |
| - var $item = $(e.currentTarget).parent(); |
3017 |
| - self.setActiveItem($item); |
3018 |
| - if (self.deleteSelection()) { |
3019 |
| - self.setCaret(self.items.length); |
3020 |
| - } |
3021 |
| - }); |
| 3083 | + // add event listener |
| 3084 | + thisRef.$control.on('click', '.' + options.className, function(e) { |
| 3085 | + e.preventDefault(); |
| 3086 | + if (self.isLocked) return; |
| 3087 | + |
| 3088 | + var $item = $(e.currentTarget).parent(); |
| 3089 | + self.setActiveItem($item); |
| 3090 | + if (self.deleteSelection()) { |
| 3091 | + self.setCaret(self.items.length); |
| 3092 | + } |
| 3093 | + }); |
3022 | 3094 |
|
| 3095 | + }; |
| 3096 | + })(); |
3023 | 3097 | };
|
3024 |
| - })(); |
3025 | 3098 |
|
| 3099 | + if (this.settings.mode === 'single') { |
| 3100 | + singleClose(this, options); |
| 3101 | + return; |
| 3102 | + } else { |
| 3103 | + multiClose(this, options); |
| 3104 | + } |
3026 | 3105 | });
|
3027 | 3106 |
|
| 3107 | + |
3028 | 3108 | Selectize.define('restore_on_backspace', function(options) {
|
3029 | 3109 | var self = this;
|
3030 | 3110 |
|
|
0 commit comments