feat: Add comprehensive documentation suite and reorganize project structure
- Created complete documentation in docs/ directory - Added PROJECT_OVERVIEW.md with feature highlights and getting started guide - Added ARCHITECTURE.md with system design and technical details - Added SECURITY.md with comprehensive security implementation guide - Added DEVELOPMENT.md with development workflows and best practices - Added DEPLOYMENT.md with production deployment instructions - Added API.md with complete REST API documentation - Added CONTRIBUTING.md with contribution guidelines - Added CHANGELOG.md with version history and migration notes - Reorganized all documentation files into docs/ directory for better organization - Updated README.md with proper documentation links and quick navigation - Enhanced project structure with professional documentation standards
This commit is contained in:
444
f_scripts/shared/simulate/jquery.simulate.key-sequence.js
Normal file
444
f_scripts/shared/simulate/jquery.simulate.key-sequence.js
Normal file
@@ -0,0 +1,444 @@
|
||||
/*jshint camelcase:true, plusplus:true, forin:true, noarg:true, noempty:true, eqeqeq:true, bitwise:true, strict:true, undef:true, unused:true, curly:true, browser:true, devel:true, maxerr:100, white:false, onevar:false */
|
||||
/*global jQuery:true $:true bililiteRange:true */
|
||||
|
||||
/* jQuery Simulate Key-Sequence Plugin 1.3.0
|
||||
* http://github.com/j-ulrich/jquery-simulate-ext
|
||||
*
|
||||
* Copyright (c) 2014 Jochen Ulrich
|
||||
* Licensed under the MIT license (MIT-LICENSE.txt).
|
||||
*
|
||||
* The plugin is an extension and modification of the jQuery sendkeys plugin by Daniel Wachsstock.
|
||||
* Therefore, the original copyright notice and license follow below.
|
||||
*/
|
||||
|
||||
// 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.0
|
||||
// Copyright (c) 2010 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($, undefined){
|
||||
"use strict";
|
||||
|
||||
$.simulate.prototype.quirks = $.simulate.prototype.quirks || {};
|
||||
|
||||
$.extend($.simulate.prototype.quirks,
|
||||
|
||||
/**
|
||||
* @lends $.simulate.prototype.quirks
|
||||
*/
|
||||
{
|
||||
/**
|
||||
* When simulating with delay in non-input elements,
|
||||
* all spaces are simulated at the end of the sequence instead
|
||||
* of the correct position.
|
||||
* @see {@link https://github.com/j-ulrich/jquery-simulate-ext/issues/6|issues #6}
|
||||
*/
|
||||
delayedSpacesInNonInputGlitchToEnd: undefined
|
||||
|
||||
});
|
||||
|
||||
$.extend($.simulate.prototype,
|
||||
|
||||
/**
|
||||
* @lends $.simulate.prototype
|
||||
*/
|
||||
{
|
||||
|
||||
/**
|
||||
* Simulates sequencial key strokes.
|
||||
*
|
||||
* @see https://github.com/j-ulrich/jquery-simulate-ext/blob/master/doc/key-sequence.md
|
||||
* @public
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
simulateKeySequence: function() {
|
||||
var target = this.target,
|
||||
$target = $(target),
|
||||
opts = $.extend({
|
||||
sequence: "",
|
||||
triggerKeyEvents: true,
|
||||
eventProps: {},
|
||||
delay: 0,
|
||||
callback: undefined
|
||||
}, this.options),
|
||||
sequence = opts.sequence;
|
||||
|
||||
opts.delay = parseInt(opts.delay,10);
|
||||
|
||||
var localkeys = {};
|
||||
|
||||
// Fix for #6 (https://github.com/j-ulrich/jquery-simulate-ext/issues/6)
|
||||
if ($.simulate.prototype.quirks.delayedSpacesInNonInputGlitchToEnd && !$target.is('input,textarea')) {
|
||||
$.extend(localkeys, {
|
||||
' ': function(rng, s, opts) {
|
||||
var internalOpts = $.extend({}, opts, {
|
||||
triggerKeyEvents: false,
|
||||
delay: 0,
|
||||
callback: undefined
|
||||
});
|
||||
$.simulate.prototype.simulateKeySequence.defaults.simplechar(rng, '\xA0', internalOpts);
|
||||
$.simulate.prototype.simulateKeySequence.defaults['{leftarrow}'](rng, s, internalOpts);
|
||||
$.simulate.prototype.simulateKeySequence.defaults.simplechar(rng, s, opts);
|
||||
$.simulate.prototype.simulateKeySequence.defaults['{del}'](rng, s, internalOpts);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.extend(localkeys, opts, $target.data('simulate-keySequence')); // 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 (target, 'simulate-keySequence.selection');
|
||||
if (!rng){
|
||||
rng = bililiteRange(target).bounds('selection');
|
||||
$.data(target, 'simulate-keySequence.selection', rng);
|
||||
$target.bind('mouseup.simulate-keySequence', 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(target, 'simulate-keySequence.selection').bounds('selection');
|
||||
}).bind('keyup.simulate-keySequence', 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(target, 'simulate-keySequence.selection').select();
|
||||
}else{
|
||||
$.data(target, 'simulate-keySequence.selection').bounds('selection');
|
||||
}
|
||||
});
|
||||
}
|
||||
$target.focus();
|
||||
if (typeof sequence === 'undefined') { // no string, so we just set up the event handlers
|
||||
return;
|
||||
}
|
||||
sequence = sequence.replace(/\n/g, '{enter}'); // turn line feeds into explicit break insertions
|
||||
|
||||
/**
|
||||
* Informs the rest of the world that the sequences is finished.
|
||||
* @fires simulate-keySequence
|
||||
* @requires target
|
||||
* @requires sequence
|
||||
* @requires opts
|
||||
* @inner
|
||||
* @author julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
function sequenceFinished() {
|
||||
$target.trigger({type: 'simulate-keySequence', sequence: sequence});
|
||||
if ($.isFunction(opts.callback)) {
|
||||
opts.callback.apply(target, [{
|
||||
sequence: sequence
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulates the key stroke for one character (or special sequence) and sleeps for
|
||||
* <code>opts.delay</code> milliseconds.
|
||||
* @requires lastTime
|
||||
* @requires now()
|
||||
* @requires tokenRegExp
|
||||
* @requires opts
|
||||
* @requires rng
|
||||
* @inner
|
||||
* @author julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
function processNextToken() {
|
||||
var timeElapsed = now() - lastTime; // Work-around for Firefox "bug": setTimeout can fire before the timeout
|
||||
if (timeElapsed >= opts.delay) {
|
||||
var match = tokenRegExp.exec(sequence);
|
||||
if ( match !== null ) {
|
||||
var s = match[0];
|
||||
(localkeys[s] || $.simulate.prototype.simulateKeySequence.defaults[s] || $.simulate.prototype.simulateKeySequence.defaults.simplechar)(rng, s, opts);
|
||||
setTimeout(processNextToken, opts.delay);
|
||||
}
|
||||
else {
|
||||
sequenceFinished();
|
||||
}
|
||||
lastTime = now();
|
||||
}
|
||||
else {
|
||||
setTimeout(processNextToken, opts.delay - timeElapsed);
|
||||
}
|
||||
}
|
||||
|
||||
if (!opts.delay || opts.delay <= 0) {
|
||||
// Run as fast as possible
|
||||
sequence.replace(/\{[^}]*\}|[^{]+/g, function(s){
|
||||
(localkeys[s] || $.simulate.prototype.simulateKeySequence.defaults[s] || $.simulate.prototype.simulateKeySequence.defaults.simplechar)(rng, s, opts);
|
||||
});
|
||||
sequenceFinished();
|
||||
}
|
||||
else {
|
||||
var tokenRegExp = /\{[^}]*\}|[^{]/g; // This matches curly bracket expressions or single characters
|
||||
var now = Date.now || function() { return new Date().getTime(); },
|
||||
lastTime = now();
|
||||
|
||||
processNextToken();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
$.extend($.simulate.prototype.simulateKeySequence.prototype,
|
||||
|
||||
/**
|
||||
* @lends $.simulate.prototype.simulateKeySequence.prototype
|
||||
*/
|
||||
{
|
||||
|
||||
/**
|
||||
* Maps special character char codes to IE key codes (covers IE and Webkit)
|
||||
* @author julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
IEKeyCodeTable: {
|
||||
33: 49, // ! -> 1
|
||||
64: 50, // @ -> 2
|
||||
35: 51, // # -> 3
|
||||
36: 52, // $ -> 4
|
||||
37: 53, // % -> 5
|
||||
94: 54, // ^ -> 6
|
||||
38: 55, // & -> 7
|
||||
42: 56, // * -> 8
|
||||
40: 57, // ( -> 9
|
||||
41: 48, // ) -> 0
|
||||
|
||||
59: 186, // ; -> 186
|
||||
58: 186, // : -> 186
|
||||
61: 187, // = -> 187
|
||||
43: 187, // + -> 187
|
||||
44: 188, // , -> 188
|
||||
60: 188, // < -> 188
|
||||
45: 189, // - -> 189
|
||||
95: 189, // _ -> 189
|
||||
46: 190, // . -> 190
|
||||
62: 190, // > -> 190
|
||||
47: 191, // / -> 191
|
||||
63: 191, // ? -> 191
|
||||
96: 192, // ` -> 192
|
||||
126: 192, // ~ -> 192
|
||||
91: 219, // [ -> 219
|
||||
123: 219, // { -> 219
|
||||
92: 220, // \ -> 220
|
||||
124: 220, // | -> 220
|
||||
93: 221, // ] -> 221
|
||||
125: 221, // } -> 221
|
||||
39: 222, // ' -> 222
|
||||
34: 222 // " -> 222
|
||||
},
|
||||
|
||||
/**
|
||||
* Tries to convert character codes to key codes.
|
||||
* @param {Numeric} character - A character code
|
||||
* @returns {Numeric} The key code corresponding to the given character code,
|
||||
* based on the key code table of InternetExplorer. If no corresponding key code
|
||||
* could be found (which will be the case for all special characters except the common
|
||||
* ones), the character code itself is returned. However, <code>keyCode === charCode</code>
|
||||
* does not imply that no key code was found because some key codes are identical to the
|
||||
* character codes (e.g. for uppercase characters).
|
||||
* @requires $.simulate.prototype.simulateKeySequence.prototype.IEKeyCodeTable
|
||||
* @see $.simulate.prototype.simulateKeySequence.prototype.IEKeyCodeTable
|
||||
* @author julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
charToKeyCode: function(character) {
|
||||
var specialKeyCodeTable = $.simulate.prototype.simulateKeySequence.prototype.IEKeyCodeTable;
|
||||
var charCode = character.charCodeAt(0);
|
||||
|
||||
if (charCode >= 64 && charCode <= 90 || charCode >= 48 && charCode <= 57) {
|
||||
// A-Z and 0-9
|
||||
return charCode;
|
||||
}
|
||||
else if (charCode >= 97 && charCode <= 122) {
|
||||
// a-z -> A-Z
|
||||
return character.toUpperCase().charCodeAt(0);
|
||||
}
|
||||
else if (specialKeyCodeTable[charCode] !== undefined) {
|
||||
return specialKeyCodeTable[charCode];
|
||||
}
|
||||
else {
|
||||
return charCode;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// add the functions publicly so they can be overridden
|
||||
$.simulate.prototype.simulateKeySequence.defaults = {
|
||||
|
||||
/**
|
||||
* Simulates key strokes of "normal" characters (i.e. non-special sequences).
|
||||
* @param {Object} rng - bililiteRange object of the simulation target element.
|
||||
* @param {String} s - String of (simple) characters to be simulated.
|
||||
* @param {Object} opts - The key-sequence options.
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
simplechar: function (rng, s, opts){
|
||||
rng.text(s, 'end');
|
||||
if (opts.triggerKeyEvents) {
|
||||
for (var i =0; i < s.length; i += 1){
|
||||
var charCode = s.charCodeAt(i);
|
||||
var keyCode = $.simulate.prototype.simulateKeySequence.prototype.charToKeyCode(s.charAt(i));
|
||||
// a bit of cheating: rng._el is the element associated with rng.
|
||||
$(rng._el).simulate('keydown', $.extend({}, opts.eventProps, {keyCode: keyCode}));
|
||||
$(rng._el).simulate('keypress', $.extend({}, opts.eventProps,{keyCode: charCode, which: charCode, charCode: charCode}));
|
||||
$(rng._el).simulate('keyup', $.extend({}, opts.eventProps, {keyCode: keyCode}));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates key strokes of a curly opening bracket.
|
||||
* @param {Object} rng - bililiteRange object of the simulation target element.
|
||||
* @param {String} s - Ignored.
|
||||
* @param {Object} opts - The key-sequence options.
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
'{{}': function (rng, s, opts){
|
||||
$.simulate.prototype.simulateKeySequence.defaults.simplechar(rng, '{', opts);
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates hitting the enter button.
|
||||
* @param {Object} rng - bililiteRange object of the simulation target element.
|
||||
* @param {String} s - Ignored.
|
||||
* @param {Object} opts - The key-sequence options.
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
'{enter}': function (rng, s, opts){
|
||||
rng.insertEOL();
|
||||
rng.select();
|
||||
if (opts.triggerKeyEvents === true) {
|
||||
$(rng._el).simulate('keydown', $.extend({}, opts.eventProps, {keyCode: 13}));
|
||||
$(rng._el).simulate('keypress', $.extend({}, opts.eventProps, {keyCode: 13, which: 13, charCode: 13}));
|
||||
$(rng._el).simulate('keyup', $.extend({}, opts.eventProps, {keyCode: 13}));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates hitting the backspace button.
|
||||
* @param {Object} rng - bililiteRange object of the simulation target element.
|
||||
* @param {String} s - Ignored.
|
||||
* @param {Object} opts - The key-sequence options.
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
'{backspace}': function (rng, s, opts){
|
||||
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
|
||||
if (opts.triggerKeyEvents === true) {
|
||||
$(rng._el).simulate('keydown', $.extend({}, opts.eventProps, {keyCode: 8}));
|
||||
$(rng._el).simulate('keyup', $.extend({}, opts.eventProps, {keyCode: 8}));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates hitting the delete button.
|
||||
* @param {Object} rng - bililiteRange object of the simulation target element.
|
||||
* @param {String} s - Ignored.
|
||||
* @param {Object} opts - The key-sequence options.
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
'{del}': function (rng, s, opts){
|
||||
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
|
||||
if (opts.triggerKeyEvents === true) {
|
||||
$(rng._el).simulate('keydown', $.extend({}, opts.eventProps, {keyCode: 46}));
|
||||
$(rng._el).simulate('keyup', $.extend({}, opts.eventProps, {keyCode: 46}));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates hitting the right arrow button.
|
||||
* @param {Object} rng - bililiteRange object of the simulation target element.
|
||||
* @param {String} s - Ignored.
|
||||
* @param {Object} opts - The key-sequence options.
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
'{rightarrow}': function (rng, s, opts){
|
||||
var b = rng.bounds();
|
||||
if (b[0] === b[1]) { b[1] += 1; } // no characters selected; it's just an insertion point. Move to the right
|
||||
rng.bounds([b[1], b[1]]).select();
|
||||
if (opts.triggerKeyEvents === true) {
|
||||
$(rng._el).simulate('keydown', $.extend({}, opts.eventProps, {keyCode: 39}));
|
||||
$(rng._el).simulate('keyup', $.extend({}, opts.eventProps, {keyCode: 39}));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Simulates hitting the left arrow button.
|
||||
* @param {Object} rng - bililiteRange object of the simulation target element.
|
||||
* @param {String} s - Ignored.
|
||||
* @param {Object} opts - The key-sequence options.
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
'{leftarrow}': function (rng, s, opts){
|
||||
var b = rng.bounds();
|
||||
if (b[0] === b[1]) { b[0] -= 1; } // no characters selected; it's just an insertion point. Move to the left
|
||||
rng.bounds([b[0], b[0]]).select();
|
||||
if (opts.triggerKeyEvents === true) {
|
||||
$(rng._el).simulate('keydown', $.extend({}, opts.eventProps, {keyCode: 37}));
|
||||
$(rng._el).simulate('keyup', $.extend({}, opts.eventProps, {keyCode: 37}));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Selects all characters in the target element.
|
||||
* @param {Object} rng - bililiteRange object of the simulation target element.
|
||||
* @author Daniel Wachsstock, julrich
|
||||
* @since 1.0
|
||||
*/
|
||||
'{selectall}' : function (rng){
|
||||
rng.bounds('all').select();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//####### Quirk detection #######
|
||||
if ($.simulate.ext_disableQuirkDetection !== true) { // Fixes issue #9 (https://github.com/j-ulrich/jquery-simulate-ext/issues/9)
|
||||
$(document).ready(function() {
|
||||
// delayedSpacesInNonInputGlitchToEnd
|
||||
// See issues #6 (https://github.com/j-ulrich/jquery-simulate-ext/issues/6)
|
||||
/* Append a div to the document (bililiteRange needs the element to be in the document), simulate
|
||||
* a delayed sequence containing a space in the middle and check if the space moves to the end.
|
||||
*/
|
||||
var $testDiv = $('<div/>').css({height: 1, width: 1, position: 'absolute', left: -1000, top: -1000}).appendTo('body');
|
||||
$testDiv.simulate('key-sequence', {sequence: '\xA0 \xA0', delay:1, callback: function() {
|
||||
$.simulate.prototype.quirks.delayedSpacesInNonInputGlitchToEnd = ($testDiv.text() === '\xA0\xA0 ');
|
||||
$testDiv.remove();
|
||||
}});
|
||||
});
|
||||
}
|
||||
|
||||
})(jQuery);
|
||||
Reference in New Issue
Block a user