diff --git a/src/tests/frontend/helper.js b/src/tests/frontend/helper.js index 18981897e..42162f892 100644 --- a/src/tests/frontend/helper.js +++ b/src/tests/frontend/helper.js @@ -36,10 +36,15 @@ const helper = {}; await p; }; - if (!win.$) await load('../../static/js/vendors/jquery.js'); - // sendkeys.js depends on jQuery, so it cannot be loaded until jQuery has finished loading. (In - // other words, do not load both jQuery and sendkeys inside a Promise.all() call.) - if (!win.bililiteRange && includeSendkeys) await load('../tests/frontend/lib/sendkeys.js'); + await Promise.all([ + !win.$ && load('../../static/js/vendors/jquery.js'), + !win.bililiteRange && includeSendkeys && load('../tests/frontend/lib/bililiteRange.js'), + ]); + // jquery.sendkeys.js depends on jQuery, so it cannot be loaded until jQuery has finished + // loading. (In other words, do not load sendkeys in the above Promise.all() call.) + if (!win.$.fn.sendkeys && includeSendkeys) { + await load('../tests/frontend/lib/jquery.sendkeys.js'); + } win.$.window = win; win.$.document = doc; diff --git a/src/tests/frontend/index.html b/src/tests/frontend/index.html index c3b7a4633..55c85c1cd 100644 --- a/src/tests/frontend/index.html +++ b/src/tests/frontend/index.html @@ -16,7 +16,8 @@ - + + diff --git a/src/tests/frontend/lib/sendkeys.js b/src/tests/frontend/lib/bililiteRange.js similarity index 77% rename from src/tests/frontend/lib/sendkeys.js rename to src/tests/frontend/lib/bililiteRange.js index 743e45b48..c56c35558 100644 --- a/src/tests/frontend/lib/sendkeys.js +++ b/src/tests/frontend/lib/bililiteRange.js @@ -404,119 +404,3 @@ NothingRange.prototype._nativeScrollIntoView = function(){ }; })(); - -// insert characters in a textarea or text input field -// special characters are enclosed in {}; use {{} for the { character itself -// documentation: http://bililite.com/blog/2008/08/20/the-fnsendkeys-plugin/ -// Version: 2.1 -// Copyright (c) 2013 Daniel Wachsstock -// MIT license: -// Permission is hereby granted, free of charge, to any person -// obtaining a copy of this software and associated documentation -// files (the "Software"), to deal in the Software without -// restriction, including without limitation the rights to use, -// copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following -// conditions: - -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -// OTHER DEALINGS IN THE SOFTWARE. - -(function($){ - -$.fn.sendkeys = function (x, opts){ - return this.each( function(){ - var localkeys = $.extend({}, opts, $(this).data('sendkeys')); // allow for element-specific key functions - // most elements to not keep track of their selection when they lose focus, so we have to do it for them - var rng = $.data (this, 'sendkeys.selection'); - if (!rng){ - rng = bililiteRange(this).bounds('selection'); - $.data(this, 'sendkeys.selection', rng); - $(this).bind('mouseup.sendkeys', function(){ - // we have to update the saved range. The routines here update the bounds with each press, but actual keypresses and mouseclicks do not - $.data(this, 'sendkeys.selection').bounds('selection'); - }).bind('keyup.sendkeys', function(evt){ - // restore the selection if we got here with a tab (a click should select what was clicked on) - if (evt.which == 9){ - // there's a flash of selection when we restore the focus, but I don't know how to avoid that. - $.data(this, 'sendkeys.selection').select(); - }else{ - $.data(this, 'sendkeys.selection').bounds('selection'); - } - }); - } - this.focus(); - if (typeof x === 'undefined') return; // no string, so we just set up the event handlers - $.data(this, 'sendkeys.originalText', rng.text()); - x.replace(/\n/g, '{enter}'). // turn line feeds into explicit break insertions - replace(/{[^}]*}|[^{]+/g, function(s){ - (localkeys[s] || $.fn.sendkeys.defaults[s] || $.fn.sendkeys.defaults.simplechar)(rng, s); - }); - $(this).trigger({type: 'sendkeys', which: x}); - }); -}; // sendkeys - - -// add the functions publicly so they can be overridden -$.fn.sendkeys.defaults = { - simplechar: function (rng, s){ - // deal with unknown {key}s - if (/^{.*}$/.test(s)) s = s.slice(1,-1); - rng.text(s, 'end'); - for (var i =0; i < s.length; ++i){ - var x = s.charCodeAt(i); - // a bit of cheating: rng._el is the element associated with rng. - $(rng._el).trigger({type: 'keypress', keyCode: x, which: x, charCode: x}); - } - }, - '{enter}': function (rng){ - rng.insertEOL(); - rng.select(); - $(rng._el).trigger({type: 'keypress', keyCode: 13, which: 13, charCode: 13, code: 'Enter', key: 'Enter'}); - }, - '{backspace}': function (rng){ - var b = rng.bounds(); - if (b[0] == b[1]) rng.bounds([b[0]-1, b[0]]); // no characters selected; it's just an insertion point. Remove the previous character - rng.text('', 'end'); // delete the characters and update the selection - }, - '{del}': function (rng){ - var b = rng.bounds(); - if (b[0] == b[1]) rng.bounds([b[0], b[0]+1]); // no characters selected; it's just an insertion point. Remove the next character - rng.text('', 'end'); // delete the characters and update the selection - }, - '{rightarrow}': function (rng){ - var b = rng.bounds(); - if (b[0] == b[1]) ++b[1]; // no characters selected; it's just an insertion point. Move to the right - rng.bounds([b[1], b[1]]).select(); - }, - '{leftarrow}': function (rng){ - var b = rng.bounds(); - if (b[0] == b[1]) --b[0]; // no characters selected; it's just an insertion point. Move to the left - rng.bounds([b[0], b[0]]).select(); - }, - '{selectall}' : function (rng){ - rng.bounds('all').select(); - }, - '{selection}': function (rng){ - $.fn.sendkeys.defaults.simplechar(rng, $.data(rng._el, 'sendkeys.originalText')); - }, - '{mark}' : function (rng){ - var bounds = rng.bounds(); - $(rng._el).one('sendkeys', function(){ - // set up the event listener to change the selection after the sendkeys is done - rng.bounds(bounds).select(); - }); - } -}; - -})(jQuery) diff --git a/src/tests/frontend/lib/jquery.sendkeys.js b/src/tests/frontend/lib/jquery.sendkeys.js new file mode 100644 index 000000000..e27f6b41f --- /dev/null +++ b/src/tests/frontend/lib/jquery.sendkeys.js @@ -0,0 +1,115 @@ +// insert characters in a textarea or text input field +// special characters are enclosed in {}; use {{} for the { character itself +// documentation: http://bililite.com/blog/2008/08/20/the-fnsendkeys-plugin/ +// Version: 2.1 +// Copyright (c) 2013 Daniel Wachsstock +// MIT license: +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: + +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +(function($){ + +$.fn.sendkeys = function (x, opts){ + return this.each( function(){ + var localkeys = $.extend({}, opts, $(this).data('sendkeys')); // allow for element-specific key functions + // most elements to not keep track of their selection when they lose focus, so we have to do it for them + var rng = $.data (this, 'sendkeys.selection'); + if (!rng){ + rng = bililiteRange(this).bounds('selection'); + $.data(this, 'sendkeys.selection', rng); + $(this).bind('mouseup.sendkeys', function(){ + // we have to update the saved range. The routines here update the bounds with each press, but actual keypresses and mouseclicks do not + $.data(this, 'sendkeys.selection').bounds('selection'); + }).bind('keyup.sendkeys', function(evt){ + // restore the selection if we got here with a tab (a click should select what was clicked on) + if (evt.which == 9){ + // there's a flash of selection when we restore the focus, but I don't know how to avoid that. + $.data(this, 'sendkeys.selection').select(); + }else{ + $.data(this, 'sendkeys.selection').bounds('selection'); + } + }); + } + this.focus(); + if (typeof x === 'undefined') return; // no string, so we just set up the event handlers + $.data(this, 'sendkeys.originalText', rng.text()); + x.replace(/\n/g, '{enter}'). // turn line feeds into explicit break insertions + replace(/{[^}]*}|[^{]+/g, function(s){ + (localkeys[s] || $.fn.sendkeys.defaults[s] || $.fn.sendkeys.defaults.simplechar)(rng, s); + }); + $(this).trigger({type: 'sendkeys', which: x}); + }); +}; // sendkeys + + +// add the functions publicly so they can be overridden +$.fn.sendkeys.defaults = { + simplechar: function (rng, s){ + // deal with unknown {key}s + if (/^{.*}$/.test(s)) s = s.slice(1,-1); + rng.text(s, 'end'); + for (var i =0; i < s.length; ++i){ + var x = s.charCodeAt(i); + // a bit of cheating: rng._el is the element associated with rng. + $(rng._el).trigger({type: 'keypress', keyCode: x, which: x, charCode: x}); + } + }, + '{enter}': function (rng){ + rng.insertEOL(); + rng.select(); + $(rng._el).trigger({type: 'keypress', keyCode: 13, which: 13, charCode: 13, code: 'Enter', key: 'Enter'}); + }, + '{backspace}': function (rng){ + var b = rng.bounds(); + if (b[0] == b[1]) rng.bounds([b[0]-1, b[0]]); // no characters selected; it's just an insertion point. Remove the previous character + rng.text('', 'end'); // delete the characters and update the selection + }, + '{del}': function (rng){ + var b = rng.bounds(); + if (b[0] == b[1]) rng.bounds([b[0], b[0]+1]); // no characters selected; it's just an insertion point. Remove the next character + rng.text('', 'end'); // delete the characters and update the selection + }, + '{rightarrow}': function (rng){ + var b = rng.bounds(); + if (b[0] == b[1]) ++b[1]; // no characters selected; it's just an insertion point. Move to the right + rng.bounds([b[1], b[1]]).select(); + }, + '{leftarrow}': function (rng){ + var b = rng.bounds(); + if (b[0] == b[1]) --b[0]; // no characters selected; it's just an insertion point. Move to the left + rng.bounds([b[0], b[0]]).select(); + }, + '{selectall}' : function (rng){ + rng.bounds('all').select(); + }, + '{selection}': function (rng){ + $.fn.sendkeys.defaults.simplechar(rng, $.data(rng._el, 'sendkeys.originalText')); + }, + '{mark}' : function (rng){ + var bounds = rng.bounds(); + $(rng._el).one('sendkeys', function(){ + // set up the event listener to change the selection after the sendkeys is done + rng.bounds(bounds).select(); + }); + } +}; + +})(jQuery)