forked from slively/ng-context-menu
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from finnlabs/feature/make_context_menu_keyboar…
…d_accessible [Feature] Make context menu keyboard accessible
- Loading branch information
Showing
7 changed files
with
300 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
/*! | ||
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 */ | ||
|
||
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(); | ||
} | ||
} | ||
} | ||
|
||
// 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; | ||
|
||
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; | ||
} | ||
|
||
if (goReverse) { | ||
nextIndex = prevIndex; | ||
} | ||
|
||
curElt = $focussable.get(nextIndex); | ||
// IE sometimes throws when an element is not visible | ||
try { | ||
curElt.focus(); | ||
} catch(e) { | ||
} | ||
|
||
} while (elt === elt.ownerDocument.activeElement); | ||
|
||
return true; | ||
} | ||
|
||
function filterKeepSpeciallyFocusable() { | ||
return this.tabIndex > 0; | ||
} | ||
|
||
function filterKeepNormalElements() { | ||
return !this.tabIndex; // true if no tabIndex or tabIndex == 0 | ||
} | ||
|
||
function sortFocusable(a, b) { | ||
return (a.t - b.t) || (a.i - b.i); | ||
} | ||
|
||
function getFocusableElementsInContainer(container) { | ||
var $container = $(container); | ||
var result = [], | ||
cnt = 0; | ||
|
||
fixIndexSelector.enable && fixIndexSelector.enable(); | ||
|
||
// 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 | ||
}); | ||
}); | ||
|
||
$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(); | ||
|
||
result = $.map(result.sort(sortFocusable), // needs stable sort | ||
function(val) { | ||
return val.v; | ||
} | ||
); | ||
|
||
|
||
return $(result); | ||
|
||
} | ||
|
||
function trap() { | ||
this.keydown(onkeypress); | ||
this.data(DATA_ISTRAPPING_KEY, true); | ||
return this; | ||
} | ||
|
||
function untrap() { | ||
this.unbind('keydown', onkeypress); | ||
this.removeData(DATA_ISTRAPPING_KEY); | ||
return this; | ||
} | ||
|
||
function isTrapping() { | ||
return !!this.data(DATA_ISTRAPPING_KEY); | ||
} | ||
|
||
$.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 | ||
|
||
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; | ||
|
||
// 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; | ||
} | ||
|
||
function fixSizzleAttrHook() { | ||
// in jQ <= 1.6.x, we add to Sizzle the attrHook from jQuery's attr method | ||
sizzleAttrHandle[tabindexKey] = sizzleAttrHandle.tabIndex = getTabindexAttr; | ||
} | ||
|
||
function unfixSizzleAttrHook() { | ||
delete sizzleAttrHandle[tabindexKey]; | ||
delete sizzleAttrHandle.tabIndex; | ||
} | ||
|
||
|
||
fixIndexSelector = { | ||
enable: fixSizzleAttrHook, | ||
disable: unfixSizzleAttrHook | ||
}; | ||
})(); | ||
} | ||
})( jQuery ); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.