OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
openproject/app/assets/javascripts/lib/jquery.trap.js

203 lines
6.2 KiB

/*!
Copyright (c) 2011, 2012 Julien Wajsberg <felash@gmail.com>
All rights reserved.
Official repository: https://github.com/julienw/jquery-trap-input
License is there: https://github.com/julienw/jquery-trap-input/blob/master/LICENSE
This is version 1.2.0.
*/
(function( $, undefined ){
/*
(this comment is after the first line of code so that uglifyjs removes it)
Redistribution and use in source and binary forms, with or without
modification, are permitted without condition.
Although that's not an obligation, I would appreciate that you provide a
link to the official repository.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED.
*/
/*jshint boss: true, bitwise: true, curly: true, expr: true, newcap: true, noarg: true, nonew: true, latedef: true, regexdash: true */
10 years ago
var DATA_ISTRAPPING_KEY = "trap.isTrapping";
function onkeypress(e) {
if (e.keyCode === 9) {
var goReverse = !!(e.shiftKey);
if (processTab(this, e.target, goReverse)) {
e.preventDefault();
e.stopPropagation();
}
}
}
10 years ago
// will return true if we could process the tab event
// otherwise, return false
function processTab(container, elt, goReverse) {
var $focussable = getFocusableElementsInContainer(container),
curElt = elt,
index, nextIndex, prevIndex, lastIndex;
10 years ago
do {
index = $focussable.index(curElt);
nextIndex = index + 1;
prevIndex = index - 1;
lastIndex = $focussable.length - 1;
switch(index) {
case -1:
return false; // that's strange, let the browser do its job
case 0:
prevIndex = lastIndex;
break;
case lastIndex:
nextIndex = 0;
break;
}
10 years ago
if (goReverse) {
nextIndex = prevIndex;
}
10 years ago
curElt = $focussable.get(nextIndex);
if (!curElt || curElt === elt) { return true; }
try {
curElt.focus();
} catch(e) { // IE sometimes throws when an element is not visible
return true;
}
} while ($focussable.length > 1 && elt === elt.ownerDocument.activeElement);
return true;
}
10 years ago
function filterKeepSpeciallyFocusable() {
return this.tabIndex > 0;
}
10 years ago
function filterKeepNormalElements() {
return !this.tabIndex; // true if no tabIndex or tabIndex == 0
}
10 years ago
function sortFocusable(a, b) {
return (a.t - b.t) || (a.i - b.i);
}
10 years ago
function getFocusableElementsInContainer(container) {
var $container = $(container);
var result = [],
cnt = 0;
fixIndexSelector.enable && fixIndexSelector.enable();
10 years ago
// leaving away command and details for now
$container.find("a[href], link[href], [draggable=true], [contenteditable=true], :input:enabled, [tabindex=0]")
.filter(":visible")
.filter(filterKeepNormalElements)
.each(function(i, val) {
result.push({
v: val, // value
t: 0, // tabIndex
i: cnt++ // index for stable sort
});
});
10 years ago
$container
.find("[tabindex]")
.filter(":visible")
.filter(filterKeepSpeciallyFocusable)
.each(function(i, val) {
result.push({
v: val, // value
t: val.tabIndex, // tabIndex
i: cnt++ // index
});
});
fixIndexSelector.disable && fixIndexSelector.disable();
10 years ago
result = $.map(result.sort(sortFocusable), // needs stable sort
function(val) {
return val.v;
}
);
10 years ago
return $(result);
10 years ago
}
10 years ago
function trap() {
this.keydown(onkeypress);
this.data(DATA_ISTRAPPING_KEY, true);
return this;
}
10 years ago
function untrap() {
this.unbind('keydown', onkeypress);
this.removeData(DATA_ISTRAPPING_KEY);
return this;
}
10 years ago
function isTrapping() {
return !!this.data(DATA_ISTRAPPING_KEY);
}
10 years ago
$.fn.extend({
trap: trap,
untrap: untrap,
isTrapping: isTrapping
});
// jQuery 1.6.x tabindex attr hooks management
// this triggers problems for tabindex attribute
// selectors in IE7-
// see https://github.com/julienw/jquery-trap-input/issues/3
10 years ago
var fixIndexSelector = {};
if ($.find.find && $.find.attr !== $.attr) {
// jQuery uses Sizzle (this is jQuery >= 1.3)
// sizzle uses its own attribute handling (in jq 1.6.x and below)
(function() {
var tabindexKey = "tabindex";
var sizzleAttrHandle = $.expr.attrHandle;
10 years ago
// this function comes directly from jQuery 1.7.2 (propHooks.tabIndex.get)
// we have to put it here if we want to support jQuery < 1.6 which
// doesn't have an attrHooks object to reference.
function getTabindexAttr(elem) {
// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
var attributeNode = elem.getAttributeNode(tabindexKey);
return attributeNode && attributeNode.specified ?
parseInt( attributeNode.value, 10 ) :
undefined;
}
10 years ago
function fixSizzleAttrHook() {
// in jQ <= 1.6.x, we add to Sizzle the attrHook from jQuery's attr method
sizzleAttrHandle[tabindexKey] = sizzleAttrHandle.tabIndex = getTabindexAttr;
}
10 years ago
function unfixSizzleAttrHook() {
delete sizzleAttrHandle[tabindexKey];
delete sizzleAttrHandle.tabIndex;
}
10 years ago
fixIndexSelector = {
enable: fixSizzleAttrHook,
disable: unfixSizzleAttrHook
};
})();
}
10 years ago
})( jQuery );