Skip to content

Fix remove_button plugin when settings.maxItems=1 #1151

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions examples/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ <h2>API</h2>

$('#button-addoption').on('click', function() {
control.addOption({
id: 4,
title: 'Something New',
value: 4,
text: 'Something New',
url: 'http://google.com'
});
});
Expand Down
7 changes: 6 additions & 1 deletion src/contrib/highlight.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ var highlight = function($element, pattern) {

var highlight = function(node) {
var skip = 0;
// Wrap matching part of text node with highlighting <span>, e.g.
// Soccer -> <span class="highlight">Soc</span>cer for regex = /soc/i
if (node.nodeType === 3) {
var pos = node.data.search(regex);
if (pos >= 0 && node.data.length > 0) {
Expand All @@ -25,7 +27,10 @@ var highlight = function($element, pattern) {
middlebit.parentNode.replaceChild(spannode, middlebit);
skip = 1;
}
} else if (node.nodeType === 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
}
// Recurse element node, looking for child text nodes to highlight, unless element
// is childless, <script>, <style>, or already highlighted: <span class="hightlight">
else if (node.nodeType === 1 && node.childNodes && !/(script|style)/i.test(node.tagName) && ( node.className !== 'highlight' || node.tagName !== 'SPAN' )) {
for (var i = 0; i < node.childNodes.length; ++i) {
i += highlight(node.childNodes[i]);
}
Expand Down
160 changes: 58 additions & 102 deletions src/plugins/remove_button/plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,109 +16,65 @@

Selectize.define('remove_button', function(options) {
options = $.extend({
label : '&times;',
title : 'Remove',
className : 'remove',
append : true
}, options);

var singleClose = function(thisRef, options) {

options.className = 'remove-single';

var self = thisRef;
var html = '<a href="javascript:void(0)" class="' + options.className + '" tabindex="-1" title="' + escape_html(options.title) + '">' + options.label + '</a>';

/**
* Appends an element as a child (with raw HTML).
*
* @param {string} html_container
* @param {string} html_element
* @return {string}
*/
var append = function(html_container, html_element) {
return $('<span>').append(html_container)
.append(html_element);
};

thisRef.setup = (function() {
var original = self.setup;
return function() {
// override the item rendering method to add the button to each
if (options.append) {
var id = $(self.$input.context).attr('id');
var selectizer = $('#'+id);

var render_item = self.settings.render.item;
self.settings.render.item = function(data) {
return append(render_item.apply(thisRef, arguments), html);
};
}

original.apply(thisRef, arguments);

// add event listener
thisRef.$control.on('click', '.' + options.className, function(e) {
e.preventDefault();
if (self.isLocked) return;

self.clear();
});

label : '&times;',
title : 'Remove',
className : 'remove',
append : true
}, options);

var self = this;
if (this.settings.mode === 'single') {
options.className = options.className || 'remove-single';
}

var html = '<a href="javascript:void(0)" class="' + options.className + '" tabindex="-1" title="' + escape_html(options.title) + '">' + options.label + '</a>';

/**
* Appends an element as a child (with raw HTML).
*
* @param {string} html_container
* @param {string} html_element
* @return {string}
*/
var append = function(html_container, html_element) {
var pos = html_container.search(/(<\/[^>]+>\s*)$/);
return html_container.substring(0, pos) + html_element + html_container.substring(pos);
};

self.setup = (function() {
var original = self.setup;
return function() {
// override the item rendering method to add the button to each
if (options.append) {
var render_item = self.settings.render.item;
self.settings.render.item = function(data) {
return append(render_item.apply(self, arguments), html);
};
})();
};

var multiClose = function(thisRef, options) {

var self = thisRef;
var html = '<a href="javascript:void(0)" class="' + options.className + '" tabindex="-1" title="' + escape_html(options.title) + '">' + options.label + '</a>';

/**
* Appends an element as a child (with raw HTML).
*
* @param {string} html_container
* @param {string} html_element
* @return {string}
*/
var append = function(html_container, html_element) {
var pos = html_container.search(/(<\/[^>]+>\s*)$/);
return html_container.substring(0, pos) + html_element + html_container.substring(pos);
};

thisRef.setup = (function() {
var original = self.setup;
return function() {
// override the item rendering method to add the button to each
if (options.append) {
var render_item = self.settings.render.item;
self.settings.render.item = function(data) {
return append(render_item.apply(thisRef, arguments), html);
};
}
}

original.apply(self, arguments);

// add event listener
self.$control.on('click', '.' + options.className, function(e) {
e.preventDefault();
if (self.isLocked) return;

// use deleteSelection()
// clear() will not trigger the 'item_remove' event
// removeItem() will not trigger the 'onDelete' callback
var $item = $(e.currentTarget).parent();

if (self.settings.mode === 'single') {
self.setCaret(); // 1 for 'single'
e['keyCode'] = KEY_BACKSPACE; // makes deleteSelection calculate the correct direction
} else {
self.setActiveItem($item);
}
if (self.deleteSelection(e)) {
self.setCaret(self.items.length);
}
});

original.apply(thisRef, arguments);

// add event listener
thisRef.$control.on('click', '.' + options.className, function(e) {
e.preventDefault();
if (self.isLocked) return;

var $item = $(e.currentTarget).parent();
self.setActiveItem($item);
if (self.deleteSelection()) {
self.setCaret(self.items.length);
}
});

};
})();
};

if (this.settings.mode === 'single') {
singleClose(this, options);
return;
} else {
multiClose(this, options);
}
})();
});
17 changes: 17 additions & 0 deletions test/interaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,23 @@
});
});

it('should not delete any dropdown option text if duplicate match occurs', function(done) {
var test = setup_test('<select>' +
'<option></option>' +
'<option value="a"></option>' +
'<option value="b">Isabel Street</option>' +
'</select>', {});

click(test.selectize.$control, function() {
// Here, the 'S' in St will also match the 's' in Isabel (a duplicate match)
syn.type('Isabel St', test.selectize.$control_input)
.delay(0, function() {
expect(test.selectize.$dropdown_content.find('.option[data-value=b]').text()).to.be.equal('Isabel Street');
done();
});
});
});

});

describe('blurring the input', function() {
Expand Down