Skip to content

Commit

Permalink
morebits/warn/xfd: Select2 related tweaks
Browse files Browse the repository at this point in the history
- Unify the code for highlightening search results from warn and xfd modules into Morebits.select2SearchHighlights
- Don't load select2 if it has already loaded.
- Don't apply select2 transformation to the select field if select2 failed to load, such as when the CDN server is down.
  • Loading branch information
siddharthvp committed Oct 15, 2019
1 parent 62aef08 commit 23eeda0
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 95 deletions.
61 changes: 14 additions & 47 deletions modules/twinklewarn.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@

Twinkle.warn = function twinklewarn() {

mw.loader.load('https://tools-static.wmflabs.org/cdnjs/ajax/libs/select2/4.0.10/js/select2.min.js');
mw.loader.load('https://tools-static.wmflabs.org/cdnjs/ajax/libs/select2/4.0.10/css/select2.min.css', 'text/css');

if (!$.fn.select2) {
mw.loader.load('https://tools-static.wmflabs.org/cdnjs/ajax/libs/select2/4.0.10/js/select2.min.js');
mw.loader.load('https://tools-static.wmflabs.org/cdnjs/ajax/libs/select2/4.0.10/css/select2.min.css', 'text/css');
}
if (mw.config.get('wgRelevantUserName')) {
Twinkle.addPortletLink(Twinkle.warn.callback, 'Warn', 'tw-warn', 'Warn/notify user');
if (Twinkle.getPref('autoMenuAfterRollback') &&
Expand Down Expand Up @@ -1162,52 +1163,18 @@ Twinkle.warn.callback.change_category = function twinklewarnCallbackChangeCatego
Twinkle.warn.callback.change_subcategory(e);

// Build select menu with select2
if (!Twinkle.getPref('oldSelect')) {
if (!Twinkle.getPref('oldSelect') && $.fn.select2) {
$('select[name=sub_group]')
.select2({ width: '100%' })
.change(Twinkle.warn.callback.change_subcategory)

// select2 natively doesn't support highlightening of search hits so we implement that here
.on('select2:open', function() {
$('.select2-search__field').keyup(function() {
var $ul = $('.select2-results__options');
$ul.find('.search-hit').each(function(i, e) {
var li_element = e.parentElement;
// This would convert <li>Hello <span class=search-hit>wo</span>rld</li>
// to <label>Hello world</label>
li_element.innerHTML = li_element.textContent;
});

if (this.value) {
var searchString = this.value;
var searchRegex = new RegExp(mw.RegExp.escape(searchString), 'i');

var $selector;
// if main_group is level1/2/3/4/4im, the ul has option groups,
// select the group header (li > strong) and the list elements (li > ul > li),
// the odd way in which select2 organises the ul necessitates this hack
if ($('select[name=main_group]').val().indexOf('level') === 0) { // can probably write as this.value.indexOf('level') === 0
$selector = 'li > strong, li > ul > li';
} else {
$selector = 'li';
}

$ul.find($selector).each(function() {
var li_text = this.textContent;
var searchHit = searchRegex.exec(li_text);
if (searchHit) {
var range = document.createRange();
var textnode = this.childNodes[0];
range.selectNodeContents(textnode);
range.setStart(textnode, searchHit.index);
range.setEnd(textnode, searchHit.index + searchString.length);
var underline_span = $('<span>').addClass('search-hit').css('text-decoration', 'underline')[0];
range.surroundContents(underline_span);
}
});
}
});
});
.change(Twinkle.warn.callback.change_subcategory);

// if main_group is level1/2/3/4/4im, the ul has option groups,
if ($('select[name=main_group]').val().indexOf('level') === 0) {
mw.select2SearchHighlights($('select[name=sub_group]'), true);
} else {
mw.select2SearchHighlights($('select[name=sub_group]'), false);
}


mw.util.addCSS(
// prevent dropdown from appearing behind the dialog
Expand Down
74 changes: 26 additions & 48 deletions modules/twinklexfd.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ Twinkle.xfd = function twinklexfd() {
if (mw.config.get('wgNamespaceNumber') < 0 || !mw.config.get('wgArticleId') || (mw.config.get('wgNamespaceNumber') === 6 && document.getElementById('mw-sharedupload'))) {
return;
}
mw.loader.load('https://tools-static.wmflabs.org/cdnjs/ajax/libs/select2/4.0.10/js/select2.min.js');
mw.loader.load('https://tools-static.wmflabs.org/cdnjs/ajax/libs/select2/4.0.10/css/select2.min.css', 'text/css');
if (!jQuery.fn.select2) {
mw.loader.load('https://tools-static.wmflabs.org/cdnjs/ajax/libs/select2/4.0.10/js/select2.min.js');
mw.loader.load('https://tools-static.wmflabs.org/cdnjs/ajax/libs/select2/4.0.10/css/select2.min.css', 'text/css');
}

Twinkle.addPortletLink(Twinkle.xfd.callback, 'XFD', 'tw-xfd', 'Start a deletion discussion');
};
Expand Down Expand Up @@ -257,57 +259,33 @@ Twinkle.xfd.callback.change_category = function twinklexfdCallbackChangeCategory
work_area = work_area.render();
old_area.parentNode.replaceChild(work_area, old_area);

$(work_area).find('[name=delsort]')
.attr('data-placeholder', 'Select delsort pages')
.select2({width: '100%'})

// select2 natively doesn't support highlightening of search hits so we implement that here
.on('select2:open', function() {
$('.select2-search__field').keyup(function() {
var $ul = $('.select2-results__options');
$ul.find('.search-hit').each(function(i, e) {
var li_element = e.parentElement;
// This would convert <li>Hello <span class=search-hit>wo</span>rld</li>
// to <label>Hello world</label>
li_element.innerHTML = li_element.textContent;
});
if ($.fn.select2) {
$(work_area).find('[name=delsort]')
.attr('data-placeholder', 'Select delsort pages')
.select2({width: '100%'});

if (this.value) {
var searchString = this.value;
var searchRegex = new RegExp(mw.RegExp.escape(searchString), 'i');
$ul.find('li > strong, li > ul > li').each(function() {
var li_text = this.textContent;
var searchHit = searchRegex.exec(li_text);
if (searchHit) {
var range = document.createRange();
var textnode = this.childNodes[0];
range.selectNodeContents(textnode);
range.setStart(textnode, searchHit.index);
range.setEnd(textnode, searchHit.index + searchString.length);
var underline_span = $('<span>').addClass('search-hit').css('text-decoration', 'underline')[0];
range.surroundContents(underline_span);
}
});
}
});
});
mw.select2SearchHighlights($('[name=delsort]'), true);

// Reduce padding
mw.util.addCSS(
// prevent dropdown from appearing behind the dialog
'.select2-container { z-index: 10000; }' +
// Reduce padding
mw.util.addCSS(
// prevent dropdown from appearing behind the dialog
'.select2-container { z-index: 10000; }' +

// Remove black border
'.select2-container--default.select2-container--focus .select2-selection--multiple { border: 1px solid #aaa; }' +
// Remove black border
'.select2-container--default.select2-container--focus .select2-selection--multiple { border: 1px solid #aaa; }' +

// Reduce padding
'.select2-results .select2-results__option { padding-top: 1px; padding-bottom: 1px; }' +
'.select2-results .select2-results__group { padding-top: 1px; padding-bottom: 1px; } ' +
// Reduce padding
'.select2-results .select2-results__option { padding-top: 1px; padding-bottom: 1px; }' +
'.select2-results .select2-results__group { padding-top: 1px; padding-bottom: 1px; } ' +

// Reduce font size
'.select2-container .select2-dropdown .select2-results { font-size: 13px; }' +
'.select2-container .selection .select2-selection__rendered { font-size: 13px; }'
);
// Reduce font size
'.select2-container .select2-dropdown .select2-results { font-size: 13px; }' +
'.select2-container .selection .select2-selection__rendered { font-size: 13px; }' +

// Make the tiny cross larger
'.select2-selection__choice__remove { font-size: 130%; }'
);
}

break;
case 'tfd':
Expand Down
48 changes: 48 additions & 0 deletions morebits.js
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@ Morebits.quickForm.element.autoNWSW = function() {
/**
* @param {HTMLElement} node
* @param {Object} data
* @requires {jquery.tipsy}
*/
Morebits.quickForm.element.generateTooltip = function QuickFormElementGenerateTooltip(node, data) {
$('<span/>', {
Expand Down Expand Up @@ -1134,6 +1135,52 @@ Morebits.array = {
}
};

/**
* select2 doesn't natively support highlightening of search hits so we implement that here
* @param {jQuery} $select
* @param {boolean} [hasOptionGroups=false] - does the select menu have optgroups?
* @requires {select2}
*/
mw.select2SearchHighlights = function select2SearchHighlights($select, hasOptionGroups) {
$select.on('select2:open', function() {
$('.select2-search__field')[0].addEventListener('keyup', function() {
var $ul = $('.select2-results__options');
$ul.find('.search-hit').each(function(_, e) {
var li_element = e.parentElement;
// This would convert <li>Hello <span class=search-hit>wo</span>rld</li>
// to <label>Hello world</label>
li_element.innerHTML = li_element.textContent;
});

if (this.value) {
var searchString = this.value;
var searchRegex = new RegExp(mw.RegExp.escape(searchString), 'i');

var selectorString;
// the odd way in which select2 organises the ul necessitates this hack
if (hasOptionGroups) {
selectorString = 'li > strong, li > ul > li';
} else {
selectorString = 'li';
}
$ul.find(selectorString).each(function() {
var li_text = this.textContent;
var searchHit = searchRegex.exec(li_text);
if (searchHit) {
var range = document.createRange();
var textnode = this.childNodes[0];
range.selectNodeContents(textnode);
range.setStart(textnode, searchHit.index);
range.setEnd(textnode, searchHit.index + searchString.length);
var underline_span = $('<span>').addClass('search-hit').css('text-decoration', 'underline')[0];
range.surroundContents(underline_span);
}
});
}
});
});
}


/**
* **************** Morebits.pageNameNorm ****************
Expand Down Expand Up @@ -3984,6 +4031,7 @@ Morebits.batchOperation = function(currentAction) {
* **************** Morebits.simpleWindow ****************
* A simple draggable window
* now a wrapper for jQuery UI's dialog feature
* @requires {jquery.ui.dialog}
*/

/**
Expand Down

0 comments on commit 23eeda0

Please sign in to comment.