Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dom-navigator

Package Overview
Dependencies
Maintainers
1
Versions
4
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dom-navigator - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

5

bower.json
{
"name": "dom-navigator",
"description": "Library that allow keyboard navigation through DOM elements (←↑→↓).",
"version": "1.0.2",
"version": "1.0.3",
"main": "dist/dom-navigator.js",

@@ -13,3 +13,4 @@ "license": "MIT",

"Gruntfile.js",
"package.json"
"package.json",
"src"
],

@@ -16,0 +17,0 @@ "keywords": [

414

dist/dom-navigator.js

@@ -1,2 +0,2 @@

/*! dom-navigator - v1.0.2 - 2014-08-19
/*! dom-navigator - v1.0.3 - 2014-08-28
* https://github.com/rmariuzzo/dom-navigator

@@ -6,7 +6,9 @@ * Copyright (c) 2014 Rubens Mariuzzo; Licensed MIT */

(function(factory) {
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], function() {
define([], function () {
return factory(window.jQuery);

@@ -19,4 +21,6 @@ });

}(function($) {
}(function ($) {
'use strict';
//-------------------//

@@ -44,2 +48,8 @@ // Utilities methods //

/**
* Add a class from an element.
*
* @param el {Element} The element.
* @param className {String} The class.
*/
function addClass(el, className) {

@@ -53,2 +63,8 @@ if (el.classList) {

/**
* Remove a class from an element.
*
* @param el {Element} The element.
* @param className {String} The class.
*/
function removeClass(el, className) {

@@ -93,2 +109,36 @@ if (el.classList) {

/**
* Return the absolute offset top of an element.
*
* @param el {Element} The element.
*
* @return {Number} The offset top.
*/
function absoluteOffsetTop(el) {
var offsetTop = 0;
do {
if (!isNaN(el.offsetTop)) {
offsetTop += el.offsetTop;
}
} while ((el = el.offsetParent));
return offsetTop;
}
/**
* Return the absolute offset left of an element.
*
* @param el {Element} The element.
*
* @return {Number} The offset left.
*/
function absoluteOffsetLeft(el) {
var offsetLeft = 0;
do {
if (!isNaN(el.offsetLeft)) {
offsetLeft += el.offsetLeft;
}
} while ((el = el.offsetParent));
return offsetLeft;
}
//-------------//

@@ -106,20 +156,34 @@ // Constructor //

*/
var Navigator = function(container, options) {
var Navigator = function (container, options) {
this.$doc = window.document;
this.$container = container;
this.$options = extend({}, Navigator.defaults, options);
this.$selected = null;
this.$keydownHandler = null;
this.$keys = {};
this.$keys[this.$options.left] = this.left;
this.$keys[this.$options.up] = this.up;
this.$keys[this.$options.right] = this.right;
this.$keys[this.$options.down] = this.down;
this.enable();
this.init();
};
/**
* Direction constants.
*/
var DIRECTION = {
left: 'left',
up: 'up',
right: 'right',
down: 'down'
};
/**
* Navigation mode constants.
*/
var MODE = {
auto: 'auto',
horizontal: 'horizontal',
vertical: 'vertical',
grid: 'grid'
};
/**
* Defaults options.
*/
Navigator.defaults = {
mode: MODE.auto,
selected: 'selected',

@@ -129,18 +193,55 @@ left: 37,

right: 39,
down: 40
down: 40,
cols: 0
};
//---------//
// Methods //
//---------//
/**
* Direction constants.
* Initialize the navigator.
*/
var DIRECTION = {
left: 'left',
up: 'up',
right: 'right',
down: 'down'
Navigator.prototype.init = function () {
this.validateOptions();
this.$selected = null;
this.$keydownHandler = null;
// Create hotkeys map.
this.$keys = {};
this.$keys[this.$options.left] = this.left;
this.$keys[this.$options.up] = this.up;
this.$keys[this.$options.right] = this.right;
this.$keys[this.$options.down] = this.down;
// Calculate cols if needed for grid mode.
if (this.$options.mode === MODE.grid && !this.$options.cols) {
var els = this.elements();
var count = [];
for (var i = 0; i < els.length; i++) {
if (i > 0 && count[i - 1] !== els[i].offsetTop) {
break;
}
count[i] = els[i].offsetTop;
}
this.$options.cols = count.length;
}
this.enable();
};
//---------//
// Methods //
//---------//
/**
* Validate current options.
*
* @return void.
*/
Navigator.prototype.validateOptions = function () {
var validMode = false;
for (var m in MODE) {
validMode = validMode || this.$options.mode === MODE[m];
}
if (!validMode) {
throw new Error('Unsupported navigation mode: ' + this.$options.mode);
}
};

@@ -152,5 +253,5 @@ /**

*/
Navigator.prototype.enable = function() {
Navigator.prototype.enable = function () {
var self = this;
this.$keydownHandler = function(event) {
this.$keydownHandler = function (event) {
self.handleKeydown.call(self, event);

@@ -166,3 +267,3 @@ };

*/
Navigator.prototype.disable = function() {
Navigator.prototype.disable = function () {
if (this.$keydownHandler) {

@@ -178,3 +279,3 @@ this.$doc.removeEventListener('keydown', this.$keydownHandler);

*/
Navigator.prototype.destroy = function() {
Navigator.prototype.destroy = function () {
this.disable();

@@ -191,10 +292,17 @@ if (this.$container.domNavigator) {

*/
Navigator.prototype.left = function() {
if (!this.$selected) {
this.select(this.elements()[0]);
} else {
Navigator.prototype.left = function () {
var next = null;
switch (this.$options.mode) {
case MODE.auto:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var left = this.$selected.offsetLeft - 1;
var top = this.$selected.offsetTop;
var next = this.elementsBefore(left, Infinity).reduce(function(prev, curr) {
next = this.elementsBefore(left, Infinity).reduce(function (prev, curr) {
var currDistance = Math.abs(left - curr.offsetLeft) + Math.abs(top - curr.offsetTop);

@@ -211,5 +319,33 @@ if (currDistance < prev.distance) {

});
next = next.element;
break;
this.select(next.element, DIRECTION.left);
case MODE.horizontal:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected.previousElementSibling;
break;
case MODE.vertical:
break;
case MODE.grid:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var index = this.elements().indexOf(this.$selected);
if (index % this.$options.cols !== 0) {
next = this.$selected.previousElementSibling;
}
break;
}
this.select(next, DIRECTION.left);
};

@@ -222,10 +358,17 @@

*/
Navigator.prototype.up = function() {
if (!this.$selected) {
this.select(this.elements()[0]);
} else {
Navigator.prototype.up = function () {
var next = null;
switch (this.$options.mode) {
case MODE.auto:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var left = this.$selected.offsetLeft;
var top = this.$selected.offsetTop - 1;
var next = this.elementsBefore(Infinity, top).reduce(function(prev, curr) {
next = this.elementsBefore(Infinity, top).reduce(function (prev, curr) {
var currDistance = Math.abs(left - curr.offsetLeft) + Math.abs(top - curr.offsetTop);

@@ -242,5 +385,32 @@ if (currDistance < prev.distance) {

});
next = next.element;
break;
this.select(next.element, DIRECTION.up);
case MODE.horizontal:
break;
case MODE.vertical:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected.previousElementSibling;
break;
case MODE.grid:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected;
for (var i = 0; i < this.$options.cols; i++) {
next = next && next.previousElementSibling;
}
break;
}
this.select(next, DIRECTION.up);
};

@@ -253,10 +423,17 @@

*/
Navigator.prototype.right = function() {
if (!this.$selected) {
this.select(this.elements()[0]);
} else {
Navigator.prototype.right = function () {
var next = null;
switch (this.$options.mode) {
case MODE.auto:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var left = this.$selected.offsetLeft + this.$selected.offsetWidth;
var top = this.$selected.offsetTop;
var next = this.elementsAfter(left, 0).reduce(function(prev, curr) {
next = this.elementsAfter(left, 0).reduce(function (prev, curr) {
var currDistance = Math.abs(curr.offsetLeft - left) + Math.abs(curr.offsetTop - top);

@@ -273,5 +450,32 @@ if (currDistance < prev.distance) {

});
next = next.element;
break;
this.select(next.element, DIRECTION.right);
case MODE.horizontal:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected.nextElementSibling;
break;
case MODE.vertical:
break;
case MODE.grid:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var index = this.elements().indexOf(this.$selected);
if (index === 0 || (index + 1) % this.$options.cols !== 0) {
next = this.$selected.nextElementSibling;
}
break;
}
this.select(next, DIRECTION.right);
};

@@ -282,10 +486,17 @@

*/
Navigator.prototype.down = function() {
if (!this.$selected) {
this.select(this.elements()[0]);
} else {
Navigator.prototype.down = function () {
var next = null;
switch (this.$options.mode) {
case MODE.auto:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var left = this.$selected.offsetLeft;
var top = this.$selected.offsetTop + this.$selected.offsetHeight;
var next = this.elementsAfter(0, top).reduce(function(prev, curr) {
next = this.elementsAfter(0, top).reduce(function (prev, curr) {
var currDistance = Math.abs(curr.offsetLeft - left) + Math.abs(curr.offsetTop - top);

@@ -302,5 +513,32 @@ if (currDistance < prev.distance) {

});
next = next.element;
break;
this.select(next.element, DIRECTION.down);
case MODE.horizontal:
break;
case MODE.vertical:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected.nextElementSibling;
break;
case MODE.grid:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected;
for (var i = 0; i < this.$options.cols; i++) {
next = next && next.nextElementSibling;
}
break;
}
this.select(next, DIRECTION.down);
};

@@ -313,3 +551,3 @@

*/
Navigator.prototype.selected = function() {
Navigator.prototype.selected = function () {
return this.$selected;

@@ -325,3 +563,3 @@ };

*/
Navigator.prototype.select = function(el, direction) {
Navigator.prototype.select = function (el, direction) {
// Is there an element or is it selected?

@@ -351,33 +589,33 @@ if (!el || el === this.$selected) {

*/
Navigator.prototype.scrollTo = function(el, direction) {
Navigator.prototype.scrollTo = function (el, direction) {
el = unboxElement(el);
if (!this.inContainerViewport(el)) {
switch (direction) {
case DIRECTION.left:
// TODO.
break;
case DIRECTION.up:
this.$container.scrollTop = el.offsetTop - this.$container.offsetTop;
break;
case DIRECTION.right:
// TODO.
break;
case DIRECTION.down:
this.$container.scrollTop = el.offsetTop - this.$container.offsetTop - (this.$container.offsetHeight - el.offsetHeight);
break;
case DIRECTION.left:
this.$container.scrollLeft = el.offsetLeft - this.$container.offsetLeft;
break;
case DIRECTION.up:
this.$container.scrollTop = el.offsetTop - this.$container.offsetTop;
break;
case DIRECTION.right:
this.$container.scrollLeft = el.offsetLeft - this.$container.offsetLeft - (this.$container.offsetWidth - el.offsetWidth);
break;
case DIRECTION.down:
this.$container.scrollTop = el.offsetTop - this.$container.offsetTop - (this.$container.offsetHeight - el.offsetHeight);
break;
}
} else if (!inViewport(el)) {
switch (direction) {
case DIRECTION.left:
document.body.scrollLeft = el.offsetLeft - document.body.offsetLeft;
break;
case DIRECTION.up:
document.body.scrollTop = el.offsetTop - document.body.offsetTop;
break;
case DIRECTION.right:
document.body.scrollLeft = el.offsetLeft - document.body.offsetLeft - (document.documentElement.clientWidth - el.offsetWidth);
break;
case DIRECTION.down:
document.body.scrollTop = el.offsetTop - document.body.offsetTop - (document.documentElement.clientHeight - el.offsetHeight);
break;
case DIRECTION.left:
document.body.scrollLeft = absoluteOffsetLeft(el) - document.body.offsetLeft;
break;
case DIRECTION.up:
document.body.scrollTop = absoluteOffsetTop(el) - document.body.offsetTop;
break;
case DIRECTION.right:
document.body.scrollLeft = absoluteOffsetLeft(el) - document.body.offsetLeft - (document.documentElement.clientWidth - el.offsetWidth);
break;
case DIRECTION.down:
document.body.scrollTop = absoluteOffsetTop(el) - document.body.offsetTop - (document.documentElement.clientHeight - el.offsetHeight);
break;
}

@@ -394,3 +632,3 @@ }

*/
Navigator.prototype.inContainerViewport = function(el) {
Navigator.prototype.inContainerViewport = function (el) {
el = unboxElement(el);

@@ -421,3 +659,3 @@ // Check on left side.

*/
Navigator.prototype.elements = function() {
Navigator.prototype.elements = function () {
var children = [];

@@ -441,4 +679,4 @@ for (var i = this.$container.children.length; i--;) {

*/
Navigator.prototype.elementsAfter = function(left, top) {
return this.elements().filter(function(el) {
Navigator.prototype.elementsAfter = function (left, top) {
return this.elements().filter(function (el) {
return el.offsetLeft >= left && el.offsetTop >= top;

@@ -456,4 +694,4 @@ });

*/
Navigator.prototype.elementsBefore = function(left, top) {
return this.elements().filter(function(el) {
Navigator.prototype.elementsBefore = function (left, top) {
return this.elements().filter(function (el) {
return el.offsetLeft <= left && el.offsetTop <= top;

@@ -470,3 +708,3 @@ });

*/
Navigator.prototype.handleKeydown = function(event) {
Navigator.prototype.handleKeydown = function (event) {
if (this.$keys[event.which]) {

@@ -492,3 +730,3 @@ event.preventDefault();

$.fn.domNavigator = function(method) {
$.fn.domNavigator = function (method) {

@@ -499,3 +737,3 @@ // Parse arguments.

this.each(function() {
this.each(function () {

@@ -527,3 +765,3 @@ // Create Navigator instance.

$.fn.domNavigator.noConflict = function() {
$.fn.domNavigator.noConflict = function () {
$.fn.domNavigator = old;

@@ -530,0 +768,0 @@ return this;

@@ -1,4 +0,4 @@

/*! dom-navigator - v1.0.2 - 2014-08-19
/*! dom-navigator - v1.0.3 - 2014-08-28
* https://github.com/rmariuzzo/dom-navigator
* Copyright (c) 2014 Rubens Mariuzzo; Licensed MIT */
!function(a){"function"==typeof define&&define.amd?define([],function(){return a(window.jQuery)}):a(window.jQuery)}(function(a){function b(a){a=a||{};for(var b=1;b<arguments.length;b++)if(arguments[b])for(var c in arguments[b])arguments[b].hasOwnProperty(c)&&(a[c]=arguments[b][c]);return a}function c(a,b){a.classList?a.classList.add(b):a.className+=" "+b}function d(a,b){a.classList?a.classList.remove(b):a.className=a.className.replace(new RegExp("(^|\\b)"+b.split(" ").join("|")+"(\\b|$)","gi")," ")}function e(a){return a.jquery||Array.isArray(a)?a[0]:a}function f(a){var b=a.getBoundingClientRect();return b.top>=0&&b.left>=0&&b.bottom<=window.innerHeight&&b.right<=window.innerWidth}var g=function(a,c){this.$doc=window.document,this.$container=a,this.$options=b({},g.defaults,c),this.$selected=null,this.$keydownHandler=null,this.$keys={},this.$keys[this.$options.left]=this.left,this.$keys[this.$options.up]=this.up,this.$keys[this.$options.right]=this.right,this.$keys[this.$options.down]=this.down,this.enable()};g.defaults={selected:"selected",left:37,up:38,right:39,down:40};var h={left:"left",up:"up",right:"right",down:"down"};if(g.prototype.enable=function(){var a=this;this.$keydownHandler=function(b){a.handleKeydown.call(a,b)},this.$doc.addEventListener("keydown",this.$keydownHandler)},g.prototype.disable=function(){this.$keydownHandler&&this.$doc.removeEventListener("keydown",this.$keydownHandler)},g.prototype.destroy=function(){this.disable(),this.$container.domNavigator&&delete this.$container.domNavigator},g.prototype.left=function(){if(this.$selected){var a=this.$selected.offsetLeft-1,b=this.$selected.offsetTop,c=this.elementsBefore(a,1/0).reduce(function(c,d){var e=Math.abs(a-d.offsetLeft)+Math.abs(b-d.offsetTop);return e<c.distance?{distance:e,element:d}:c},{distance:1/0});this.select(c.element,h.left)}else this.select(this.elements()[0])},g.prototype.up=function(){if(this.$selected){var a=this.$selected.offsetLeft,b=this.$selected.offsetTop-1,c=this.elementsBefore(1/0,b).reduce(function(c,d){var e=Math.abs(a-d.offsetLeft)+Math.abs(b-d.offsetTop);return e<c.distance?{distance:e,element:d}:c},{distance:1/0});this.select(c.element,h.up)}else this.select(this.elements()[0])},g.prototype.right=function(){if(this.$selected){var a=this.$selected.offsetLeft+this.$selected.offsetWidth,b=this.$selected.offsetTop,c=this.elementsAfter(a,0).reduce(function(c,d){var e=Math.abs(d.offsetLeft-a)+Math.abs(d.offsetTop-b);return e<c.distance?{distance:e,element:d}:c},{distance:1/0});this.select(c.element,h.right)}else this.select(this.elements()[0])},g.prototype.down=function(){if(this.$selected){var a=this.$selected.offsetLeft,b=this.$selected.offsetTop+this.$selected.offsetHeight,c=this.elementsAfter(0,b).reduce(function(c,d){var e=Math.abs(d.offsetLeft-a)+Math.abs(d.offsetTop-b);return e<c.distance?{distance:e,element:d}:c},{distance:1/0});this.select(c.element,h.down)}else this.select(this.elements()[0])},g.prototype.selected=function(){return this.$selected},g.prototype.select=function(a,b){a&&a!==this.$selected&&(a=e(a),this.$selected&&d(this.$selected,this.$options.selected),this.scrollTo(a,b),c(a,this.$options.selected),this.$selected=a)},g.prototype.scrollTo=function(a,b){if(a=e(a),this.inContainerViewport(a)){if(!f(a))switch(b){case h.left:document.body.scrollLeft=a.offsetLeft-document.body.offsetLeft;break;case h.up:document.body.scrollTop=a.offsetTop-document.body.offsetTop;break;case h.right:document.body.scrollLeft=a.offsetLeft-document.body.offsetLeft-(document.documentElement.clientWidth-a.offsetWidth);break;case h.down:document.body.scrollTop=a.offsetTop-document.body.offsetTop-(document.documentElement.clientHeight-a.offsetHeight)}}else switch(b){case h.left:break;case h.up:this.$container.scrollTop=a.offsetTop-this.$container.offsetTop;break;case h.right:break;case h.down:this.$container.scrollTop=a.offsetTop-this.$container.offsetTop-(this.$container.offsetHeight-a.offsetHeight)}},g.prototype.inContainerViewport=function(a){return a=e(a),a.offsetLeft-this.$container.scrollLeft<this.$container.offsetLeft?!1:a.offsetTop-this.$container.scrollTop<this.$container.offsetTop?!1:a.offsetLeft+a.offsetWidth-this.$container.scrollLeft>this.$container.offsetLeft+this.$container.offsetWidth?!1:a.offsetTop+a.offsetHeight-this.$container.scrollTop>this.$container.offsetTop+this.$container.offsetHeight?!1:!0},g.prototype.elements=function(){for(var a=[],b=this.$container.children.length;b--;)8!==this.$container.children[b].nodeType&&a.unshift(this.$container.children[b]);return a},g.prototype.elementsAfter=function(a,b){return this.elements().filter(function(c){return c.offsetLeft>=a&&c.offsetTop>=b})},g.prototype.elementsBefore=function(a,b){return this.elements().filter(function(c){return c.offsetLeft<=a&&c.offsetTop<=b})},g.prototype.handleKeydown=function(a){this.$keys[a.which]&&(a.preventDefault(),this.$keys[a.which].call(this))},window.DomNavigator=g,a){var i=a.fn.domNavigator;a.fn.domNavigator=function(a){var b,c=Array.prototype.slice.call(arguments,1);return this.each(function(){this.domNavigator||(this.domNavigator=new g(this,"object"==typeof a&&a)),"string"==typeof a&&this.domNavigator[a]&&(b=this.domNavigator[a].apply(this.domNavigator,c))}),void 0===b&&(b=this),b},a.fn.domNavigator.Constructor=g,a.fn.domNavigator.noConflict=function(){return a.fn.domNavigator=i,this}}});
!function(a){"use strict";"function"==typeof define&&define.amd?define([],function(){return a(window.jQuery)}):a(window.jQuery)}(function(a){"use strict";function b(a){a=a||{};for(var b=1;b<arguments.length;b++)if(arguments[b])for(var c in arguments[b])arguments[b].hasOwnProperty(c)&&(a[c]=arguments[b][c]);return a}function c(a,b){a.classList?a.classList.add(b):a.className+=" "+b}function d(a,b){a.classList?a.classList.remove(b):a.className=a.className.replace(new RegExp("(^|\\b)"+b.split(" ").join("|")+"(\\b|$)","gi")," ")}function e(a){return a.jquery||Array.isArray(a)?a[0]:a}function f(a){var b=a.getBoundingClientRect();return b.top>=0&&b.left>=0&&b.bottom<=window.innerHeight&&b.right<=window.innerWidth}function g(a){var b=0;do isNaN(a.offsetTop)||(b+=a.offsetTop);while(a=a.offsetParent);return b}function h(a){var b=0;do isNaN(a.offsetLeft)||(b+=a.offsetLeft);while(a=a.offsetParent);return b}var i=function(a,c){this.$doc=window.document,this.$container=a,this.$options=b({},i.defaults,c),this.init()},j={left:"left",up:"up",right:"right",down:"down"},k={auto:"auto",horizontal:"horizontal",vertical:"vertical",grid:"grid"};if(i.defaults={mode:k.auto,selected:"selected",left:37,up:38,right:39,down:40,cols:0},i.prototype.init=function(){if(this.validateOptions(),this.$selected=null,this.$keydownHandler=null,this.$keys={},this.$keys[this.$options.left]=this.left,this.$keys[this.$options.up]=this.up,this.$keys[this.$options.right]=this.right,this.$keys[this.$options.down]=this.down,this.$options.mode===k.grid&&!this.$options.cols){for(var a=this.elements(),b=[],c=0;c<a.length&&!(c>0&&b[c-1]!==a[c].offsetTop);c++)b[c]=a[c].offsetTop;this.$options.cols=b.length}this.enable()},i.prototype.validateOptions=function(){var a=!1;for(var b in k)a=a||this.$options.mode===k[b];if(!a)throw new Error("Unsupported navigation mode: "+this.$options.mode)},i.prototype.enable=function(){var a=this;this.$keydownHandler=function(b){a.handleKeydown.call(a,b)},this.$doc.addEventListener("keydown",this.$keydownHandler)},i.prototype.disable=function(){this.$keydownHandler&&this.$doc.removeEventListener("keydown",this.$keydownHandler)},i.prototype.destroy=function(){this.disable(),this.$container.domNavigator&&delete this.$container.domNavigator},i.prototype.left=function(){var a=null;switch(this.$options.mode){case k.auto:if(!this.$selected){a=this.elements()[0];break}var b=this.$selected.offsetLeft-1,c=this.$selected.offsetTop;a=this.elementsBefore(b,1/0).reduce(function(a,d){var e=Math.abs(b-d.offsetLeft)+Math.abs(c-d.offsetTop);return e<a.distance?{distance:e,element:d}:a},{distance:1/0}),a=a.element;break;case k.horizontal:if(!this.$selected){a=this.elements()[0];break}a=this.$selected.previousElementSibling;break;case k.vertical:break;case k.grid:if(!this.$selected){a=this.elements()[0];break}var d=this.elements().indexOf(this.$selected);d%this.$options.cols!==0&&(a=this.$selected.previousElementSibling)}this.select(a,j.left)},i.prototype.up=function(){var a=null;switch(this.$options.mode){case k.auto:if(!this.$selected){a=this.elements()[0];break}var b=this.$selected.offsetLeft,c=this.$selected.offsetTop-1;a=this.elementsBefore(1/0,c).reduce(function(a,d){var e=Math.abs(b-d.offsetLeft)+Math.abs(c-d.offsetTop);return e<a.distance?{distance:e,element:d}:a},{distance:1/0}),a=a.element;break;case k.horizontal:break;case k.vertical:if(!this.$selected){a=this.elements()[0];break}a=this.$selected.previousElementSibling;break;case k.grid:if(!this.$selected){a=this.elements()[0];break}a=this.$selected;for(var d=0;d<this.$options.cols;d++)a=a&&a.previousElementSibling}this.select(a,j.up)},i.prototype.right=function(){var a=null;switch(this.$options.mode){case k.auto:if(!this.$selected){a=this.elements()[0];break}var b=this.$selected.offsetLeft+this.$selected.offsetWidth,c=this.$selected.offsetTop;a=this.elementsAfter(b,0).reduce(function(a,d){var e=Math.abs(d.offsetLeft-b)+Math.abs(d.offsetTop-c);return e<a.distance?{distance:e,element:d}:a},{distance:1/0}),a=a.element;break;case k.horizontal:if(!this.$selected){a=this.elements()[0];break}a=this.$selected.nextElementSibling;break;case k.vertical:break;case k.grid:if(!this.$selected){a=this.elements()[0];break}var d=this.elements().indexOf(this.$selected);(0===d||(d+1)%this.$options.cols!==0)&&(a=this.$selected.nextElementSibling)}this.select(a,j.right)},i.prototype.down=function(){var a=null;switch(this.$options.mode){case k.auto:if(!this.$selected){a=this.elements()[0];break}var b=this.$selected.offsetLeft,c=this.$selected.offsetTop+this.$selected.offsetHeight;a=this.elementsAfter(0,c).reduce(function(a,d){var e=Math.abs(d.offsetLeft-b)+Math.abs(d.offsetTop-c);return e<a.distance?{distance:e,element:d}:a},{distance:1/0}),a=a.element;break;case k.horizontal:break;case k.vertical:if(!this.$selected){a=this.elements()[0];break}a=this.$selected.nextElementSibling;break;case k.grid:if(!this.$selected){a=this.elements()[0];break}a=this.$selected;for(var d=0;d<this.$options.cols;d++)a=a&&a.nextElementSibling}this.select(a,j.down)},i.prototype.selected=function(){return this.$selected},i.prototype.select=function(a,b){a&&a!==this.$selected&&(a=e(a),this.$selected&&d(this.$selected,this.$options.selected),this.scrollTo(a,b),c(a,this.$options.selected),this.$selected=a)},i.prototype.scrollTo=function(a,b){if(a=e(a),this.inContainerViewport(a)){if(!f(a))switch(b){case j.left:document.body.scrollLeft=h(a)-document.body.offsetLeft;break;case j.up:document.body.scrollTop=g(a)-document.body.offsetTop;break;case j.right:document.body.scrollLeft=h(a)-document.body.offsetLeft-(document.documentElement.clientWidth-a.offsetWidth);break;case j.down:document.body.scrollTop=g(a)-document.body.offsetTop-(document.documentElement.clientHeight-a.offsetHeight)}}else switch(b){case j.left:this.$container.scrollLeft=a.offsetLeft-this.$container.offsetLeft;break;case j.up:this.$container.scrollTop=a.offsetTop-this.$container.offsetTop;break;case j.right:this.$container.scrollLeft=a.offsetLeft-this.$container.offsetLeft-(this.$container.offsetWidth-a.offsetWidth);break;case j.down:this.$container.scrollTop=a.offsetTop-this.$container.offsetTop-(this.$container.offsetHeight-a.offsetHeight)}},i.prototype.inContainerViewport=function(a){return a=e(a),a.offsetLeft-this.$container.scrollLeft<this.$container.offsetLeft?!1:a.offsetTop-this.$container.scrollTop<this.$container.offsetTop?!1:a.offsetLeft+a.offsetWidth-this.$container.scrollLeft>this.$container.offsetLeft+this.$container.offsetWidth?!1:a.offsetTop+a.offsetHeight-this.$container.scrollTop>this.$container.offsetTop+this.$container.offsetHeight?!1:!0},i.prototype.elements=function(){for(var a=[],b=this.$container.children.length;b--;)8!==this.$container.children[b].nodeType&&a.unshift(this.$container.children[b]);return a},i.prototype.elementsAfter=function(a,b){return this.elements().filter(function(c){return c.offsetLeft>=a&&c.offsetTop>=b})},i.prototype.elementsBefore=function(a,b){return this.elements().filter(function(c){return c.offsetLeft<=a&&c.offsetTop<=b})},i.prototype.handleKeydown=function(a){this.$keys[a.which]&&(a.preventDefault(),this.$keys[a.which].call(this))},window.DomNavigator=i,a){var l=a.fn.domNavigator;a.fn.domNavigator=function(a){var b,c=Array.prototype.slice.call(arguments,1);return this.each(function(){this.domNavigator||(this.domNavigator=new i(this,"object"==typeof a&&a)),"string"==typeof a&&this.domNavigator[a]&&(b=this.domNavigator[a].apply(this.domNavigator,c))}),void 0===b&&(b=this),b},a.fn.domNavigator.Constructor=i,a.fn.domNavigator.noConflict=function(){return a.fn.domNavigator=l,this}}});
{
"name": "dom-navigator",
"version": "1.0.2",
"version": "1.0.3",
"description": "Library that allow keyboard navigation through DOM elements (←↑→↓).",
"keywords": [
"dom", "navigator", "navigaton"
"dom-navigator",
"javascript",
"js",
"dom",
"navigator",
"navigation",
"jquery"
],

@@ -8,0 +14,0 @@ "homepage": "https://github.com/rmariuzzo/dom-navigator",

@@ -11,7 +11,9 @@ /*

(function(factory) {
(function (factory) {
'use strict';
if (typeof define === 'function' && define.amd) {
// AMD. Register as an anonymous module.
define([], function() {
define([], function () {
return factory(window.jQuery);

@@ -24,4 +26,6 @@ });

}(function($) {
}(function ($) {
'use strict';
//-------------------//

@@ -49,2 +53,8 @@ // Utilities methods //

/**
* Add a class from an element.
*
* @param el {Element} The element.
* @param className {String} The class.
*/
function addClass(el, className) {

@@ -58,2 +68,8 @@ if (el.classList) {

/**
* Remove a class from an element.
*
* @param el {Element} The element.
* @param className {String} The class.
*/
function removeClass(el, className) {

@@ -98,2 +114,36 @@ if (el.classList) {

/**
* Return the absolute offset top of an element.
*
* @param el {Element} The element.
*
* @return {Number} The offset top.
*/
function absoluteOffsetTop(el) {
var offsetTop = 0;
do {
if (!isNaN(el.offsetTop)) {
offsetTop += el.offsetTop;
}
} while ((el = el.offsetParent));
return offsetTop;
}
/**
* Return the absolute offset left of an element.
*
* @param el {Element} The element.
*
* @return {Number} The offset left.
*/
function absoluteOffsetLeft(el) {
var offsetLeft = 0;
do {
if (!isNaN(el.offsetLeft)) {
offsetLeft += el.offsetLeft;
}
} while ((el = el.offsetParent));
return offsetLeft;
}
//-------------//

@@ -111,20 +161,34 @@ // Constructor //

*/
var Navigator = function(container, options) {
var Navigator = function (container, options) {
this.$doc = window.document;
this.$container = container;
this.$options = extend({}, Navigator.defaults, options);
this.$selected = null;
this.$keydownHandler = null;
this.$keys = {};
this.$keys[this.$options.left] = this.left;
this.$keys[this.$options.up] = this.up;
this.$keys[this.$options.right] = this.right;
this.$keys[this.$options.down] = this.down;
this.enable();
this.init();
};
/**
* Direction constants.
*/
var DIRECTION = {
left: 'left',
up: 'up',
right: 'right',
down: 'down'
};
/**
* Navigation mode constants.
*/
var MODE = {
auto: 'auto',
horizontal: 'horizontal',
vertical: 'vertical',
grid: 'grid'
};
/**
* Defaults options.
*/
Navigator.defaults = {
mode: MODE.auto,
selected: 'selected',

@@ -134,18 +198,55 @@ left: 37,

right: 39,
down: 40
down: 40,
cols: 0
};
//---------//
// Methods //
//---------//
/**
* Direction constants.
* Initialize the navigator.
*/
var DIRECTION = {
left: 'left',
up: 'up',
right: 'right',
down: 'down'
Navigator.prototype.init = function () {
this.validateOptions();
this.$selected = null;
this.$keydownHandler = null;
// Create hotkeys map.
this.$keys = {};
this.$keys[this.$options.left] = this.left;
this.$keys[this.$options.up] = this.up;
this.$keys[this.$options.right] = this.right;
this.$keys[this.$options.down] = this.down;
// Calculate cols if needed for grid mode.
if (this.$options.mode === MODE.grid && !this.$options.cols) {
var els = this.elements();
var count = [];
for (var i = 0; i < els.length; i++) {
if (i > 0 && count[i - 1] !== els[i].offsetTop) {
break;
}
count[i] = els[i].offsetTop;
}
this.$options.cols = count.length;
}
this.enable();
};
//---------//
// Methods //
//---------//
/**
* Validate current options.
*
* @return void.
*/
Navigator.prototype.validateOptions = function () {
var validMode = false;
for (var m in MODE) {
validMode = validMode || this.$options.mode === MODE[m];
}
if (!validMode) {
throw new Error('Unsupported navigation mode: ' + this.$options.mode);
}
};

@@ -157,5 +258,5 @@ /**

*/
Navigator.prototype.enable = function() {
Navigator.prototype.enable = function () {
var self = this;
this.$keydownHandler = function(event) {
this.$keydownHandler = function (event) {
self.handleKeydown.call(self, event);

@@ -171,3 +272,3 @@ };

*/
Navigator.prototype.disable = function() {
Navigator.prototype.disable = function () {
if (this.$keydownHandler) {

@@ -183,3 +284,3 @@ this.$doc.removeEventListener('keydown', this.$keydownHandler);

*/
Navigator.prototype.destroy = function() {
Navigator.prototype.destroy = function () {
this.disable();

@@ -196,10 +297,17 @@ if (this.$container.domNavigator) {

*/
Navigator.prototype.left = function() {
if (!this.$selected) {
this.select(this.elements()[0]);
} else {
Navigator.prototype.left = function () {
var next = null;
switch (this.$options.mode) {
case MODE.auto:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var left = this.$selected.offsetLeft - 1;
var top = this.$selected.offsetTop;
var next = this.elementsBefore(left, Infinity).reduce(function(prev, curr) {
next = this.elementsBefore(left, Infinity).reduce(function (prev, curr) {
var currDistance = Math.abs(left - curr.offsetLeft) + Math.abs(top - curr.offsetTop);

@@ -216,5 +324,33 @@ if (currDistance < prev.distance) {

});
next = next.element;
break;
this.select(next.element, DIRECTION.left);
case MODE.horizontal:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected.previousElementSibling;
break;
case MODE.vertical:
break;
case MODE.grid:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var index = this.elements().indexOf(this.$selected);
if (index % this.$options.cols !== 0) {
next = this.$selected.previousElementSibling;
}
break;
}
this.select(next, DIRECTION.left);
};

@@ -227,10 +363,17 @@

*/
Navigator.prototype.up = function() {
if (!this.$selected) {
this.select(this.elements()[0]);
} else {
Navigator.prototype.up = function () {
var next = null;
switch (this.$options.mode) {
case MODE.auto:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var left = this.$selected.offsetLeft;
var top = this.$selected.offsetTop - 1;
var next = this.elementsBefore(Infinity, top).reduce(function(prev, curr) {
next = this.elementsBefore(Infinity, top).reduce(function (prev, curr) {
var currDistance = Math.abs(left - curr.offsetLeft) + Math.abs(top - curr.offsetTop);

@@ -247,5 +390,32 @@ if (currDistance < prev.distance) {

});
next = next.element;
break;
this.select(next.element, DIRECTION.up);
case MODE.horizontal:
break;
case MODE.vertical:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected.previousElementSibling;
break;
case MODE.grid:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected;
for (var i = 0; i < this.$options.cols; i++) {
next = next && next.previousElementSibling;
}
break;
}
this.select(next, DIRECTION.up);
};

@@ -258,10 +428,17 @@

*/
Navigator.prototype.right = function() {
if (!this.$selected) {
this.select(this.elements()[0]);
} else {
Navigator.prototype.right = function () {
var next = null;
switch (this.$options.mode) {
case MODE.auto:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var left = this.$selected.offsetLeft + this.$selected.offsetWidth;
var top = this.$selected.offsetTop;
var next = this.elementsAfter(left, 0).reduce(function(prev, curr) {
next = this.elementsAfter(left, 0).reduce(function (prev, curr) {
var currDistance = Math.abs(curr.offsetLeft - left) + Math.abs(curr.offsetTop - top);

@@ -278,5 +455,32 @@ if (currDistance < prev.distance) {

});
next = next.element;
break;
this.select(next.element, DIRECTION.right);
case MODE.horizontal:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected.nextElementSibling;
break;
case MODE.vertical:
break;
case MODE.grid:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var index = this.elements().indexOf(this.$selected);
if (index === 0 || (index + 1) % this.$options.cols !== 0) {
next = this.$selected.nextElementSibling;
}
break;
}
this.select(next, DIRECTION.right);
};

@@ -287,10 +491,17 @@

*/
Navigator.prototype.down = function() {
if (!this.$selected) {
this.select(this.elements()[0]);
} else {
Navigator.prototype.down = function () {
var next = null;
switch (this.$options.mode) {
case MODE.auto:
if (!this.$selected) {
next = this.elements()[0];
break;
}
var left = this.$selected.offsetLeft;
var top = this.$selected.offsetTop + this.$selected.offsetHeight;
var next = this.elementsAfter(0, top).reduce(function(prev, curr) {
next = this.elementsAfter(0, top).reduce(function (prev, curr) {
var currDistance = Math.abs(curr.offsetLeft - left) + Math.abs(curr.offsetTop - top);

@@ -307,5 +518,32 @@ if (currDistance < prev.distance) {

});
next = next.element;
break;
this.select(next.element, DIRECTION.down);
case MODE.horizontal:
break;
case MODE.vertical:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected.nextElementSibling;
break;
case MODE.grid:
if (!this.$selected) {
next = this.elements()[0];
break;
}
next = this.$selected;
for (var i = 0; i < this.$options.cols; i++) {
next = next && next.nextElementSibling;
}
break;
}
this.select(next, DIRECTION.down);
};

@@ -318,3 +556,3 @@

*/
Navigator.prototype.selected = function() {
Navigator.prototype.selected = function () {
return this.$selected;

@@ -330,3 +568,3 @@ };

*/
Navigator.prototype.select = function(el, direction) {
Navigator.prototype.select = function (el, direction) {
// Is there an element or is it selected?

@@ -356,33 +594,33 @@ if (!el || el === this.$selected) {

*/
Navigator.prototype.scrollTo = function(el, direction) {
Navigator.prototype.scrollTo = function (el, direction) {
el = unboxElement(el);
if (!this.inContainerViewport(el)) {
switch (direction) {
case DIRECTION.left:
// TODO.
break;
case DIRECTION.up:
this.$container.scrollTop = el.offsetTop - this.$container.offsetTop;
break;
case DIRECTION.right:
// TODO.
break;
case DIRECTION.down:
this.$container.scrollTop = el.offsetTop - this.$container.offsetTop - (this.$container.offsetHeight - el.offsetHeight);
break;
case DIRECTION.left:
this.$container.scrollLeft = el.offsetLeft - this.$container.offsetLeft;
break;
case DIRECTION.up:
this.$container.scrollTop = el.offsetTop - this.$container.offsetTop;
break;
case DIRECTION.right:
this.$container.scrollLeft = el.offsetLeft - this.$container.offsetLeft - (this.$container.offsetWidth - el.offsetWidth);
break;
case DIRECTION.down:
this.$container.scrollTop = el.offsetTop - this.$container.offsetTop - (this.$container.offsetHeight - el.offsetHeight);
break;
}
} else if (!inViewport(el)) {
switch (direction) {
case DIRECTION.left:
document.body.scrollLeft = el.offsetLeft - document.body.offsetLeft;
break;
case DIRECTION.up:
document.body.scrollTop = el.offsetTop - document.body.offsetTop;
break;
case DIRECTION.right:
document.body.scrollLeft = el.offsetLeft - document.body.offsetLeft - (document.documentElement.clientWidth - el.offsetWidth);
break;
case DIRECTION.down:
document.body.scrollTop = el.offsetTop - document.body.offsetTop - (document.documentElement.clientHeight - el.offsetHeight);
break;
case DIRECTION.left:
document.body.scrollLeft = absoluteOffsetLeft(el) - document.body.offsetLeft;
break;
case DIRECTION.up:
document.body.scrollTop = absoluteOffsetTop(el) - document.body.offsetTop;
break;
case DIRECTION.right:
document.body.scrollLeft = absoluteOffsetLeft(el) - document.body.offsetLeft - (document.documentElement.clientWidth - el.offsetWidth);
break;
case DIRECTION.down:
document.body.scrollTop = absoluteOffsetTop(el) - document.body.offsetTop - (document.documentElement.clientHeight - el.offsetHeight);
break;
}

@@ -399,3 +637,3 @@ }

*/
Navigator.prototype.inContainerViewport = function(el) {
Navigator.prototype.inContainerViewport = function (el) {
el = unboxElement(el);

@@ -426,3 +664,3 @@ // Check on left side.

*/
Navigator.prototype.elements = function() {
Navigator.prototype.elements = function () {
var children = [];

@@ -446,4 +684,4 @@ for (var i = this.$container.children.length; i--;) {

*/
Navigator.prototype.elementsAfter = function(left, top) {
return this.elements().filter(function(el) {
Navigator.prototype.elementsAfter = function (left, top) {
return this.elements().filter(function (el) {
return el.offsetLeft >= left && el.offsetTop >= top;

@@ -461,4 +699,4 @@ });

*/
Navigator.prototype.elementsBefore = function(left, top) {
return this.elements().filter(function(el) {
Navigator.prototype.elementsBefore = function (left, top) {
return this.elements().filter(function (el) {
return el.offsetLeft <= left && el.offsetTop <= top;

@@ -475,3 +713,3 @@ });

*/
Navigator.prototype.handleKeydown = function(event) {
Navigator.prototype.handleKeydown = function (event) {
if (this.$keys[event.which]) {

@@ -497,3 +735,3 @@ event.preventDefault();

$.fn.domNavigator = function(method) {
$.fn.domNavigator = function (method) {

@@ -504,3 +742,3 @@ // Parse arguments.

this.each(function() {
this.each(function () {

@@ -532,3 +770,3 @@ // Create Navigator instance.

$.fn.domNavigator.noConflict = function() {
$.fn.domNavigator.noConflict = function () {
$.fn.domNavigator = old;

@@ -535,0 +773,0 @@ return this;

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc