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.0 to 1.0.1

test/demo_jquery.html

2

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

@@ -6,0 +6,0 @@ "license": "MIT",

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

/*! dom-navigator - v1.0.0 - 2014-08-13
/*! dom-navigator - v1.0.1 - 2014-08-16
* https://github.com/rmariuzzo/dom-navigator

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

define([], function() {
return factory(jQuery);
return factory(window.jQuery);
});
} else {
// Browser globals
factory(jQuery);
factory(window.jQuery);
}

@@ -59,2 +59,16 @@

/**
* Unbox an object from jQuery or array.
*
* @param obj {Object} The object to unbox.
*
* @return {Element} An element.
*/
function unboxElement(obj) {
if (obj.jquery || Array.isArray(obj)) {
return obj[0];
}
return obj;
}
//-------------//

@@ -64,7 +78,16 @@ // Constructor //

var Navigator = function(element, options) {
/**
* Create a new DOM Navigator.
*
* @param container {Element} The container of the element to navigate.
* @param options {Object} The options to configure the DOM navigator.
*
* @return void.
*/
var Navigator = function(container, options) {
this.$doc = window.document;
this.$element = element;
this.$container = container;
this.$options = extend({}, Navigator.defaults, options);
this.$selected = null;
this.$keydownHandler = null;
this.$keys = {};

@@ -75,6 +98,8 @@ this.$keys[this.$options.left] = this.left;

this.$keys[this.$options.down] = this.down;
this.$keydownHandler = null;
this.enable();
};
/**
* Defaults options.
*/
Navigator.defaults = {

@@ -88,2 +113,12 @@ selected: 'selected',

/**
* Direction constants.
*/
var DIRECTION = {
left: 'left',
up: 'up',
right: 'right',
down: 'down'
};
//---------//

@@ -93,2 +128,7 @@ // Methods //

/**
* Enable this navigator.
*
* @return void.
*/
Navigator.prototype.enable = function() {

@@ -102,2 +142,7 @@ var self = this;

/**
* Disable this navigator.
*
* @return void.
*/
Navigator.prototype.disable = function() {

@@ -109,9 +154,19 @@ if (this.$keydownHandler) {

/**
* Destroy this navigator removing any event registered and any other data.
*
* @return void.
*/
Navigator.prototype.destroy = function() {
this.disable();
if (this.$element.domNavigator) {
delete this.$element.domNavigator;
if (this.$container.domNavigator) {
delete this.$container.domNavigator;
}
};
/**
* Navigate left to the next element if any.
*
* @return void.
*/
Navigator.prototype.left = function() {

@@ -125,5 +180,3 @@ if (!this.$selected) {

var next = this.elementsBefore(left, Infinity).reduce(function(prev, curr) {
curr = $(curr);
var currDistance = curr.position();
currDistance = Math.abs(left - currDistance.left) + Math.abs(top - currDistance.top);
var currDistance = Math.abs(left - curr.offsetLeft) + Math.abs(top - curr.offsetTop);
if (currDistance < prev.distance) {

@@ -140,6 +193,11 @@ return {

this.select(next.element);
this.select(next.element, DIRECTION.left);
}
};
/**
* Navigate up to the next element if any.
*
* @return void.
*/
Navigator.prototype.up = function() {

@@ -153,5 +211,3 @@ if (!this.$selected) {

var next = this.elementsBefore(Infinity, top).reduce(function(prev, curr) {
curr = $(curr);
var currDistance = curr.position();
currDistance = Math.abs(left - currDistance.left) + Math.abs(top - currDistance.top);
var currDistance = Math.abs(left - curr.offsetLeft) + Math.abs(top - curr.offsetTop);
if (currDistance < prev.distance) {

@@ -168,6 +224,11 @@ return {

this.select(next.element);
this.select(next.element, DIRECTION.up);
}
};
/**
* Navigate right to the next element if any.
*
* @return void.
*/
Navigator.prototype.right = function() {

@@ -181,5 +242,3 @@ if (!this.$selected) {

var next = this.elementsAfter(left, 0).reduce(function(prev, curr) {
curr = $(curr);
var currDistance = curr.position();
currDistance = Math.abs(currDistance.left - left) + Math.abs(currDistance.top - top);
var currDistance = Math.abs(curr.offsetLeft - left) + Math.abs(curr.offsetTop - top);
if (currDistance < prev.distance) {

@@ -196,6 +255,9 @@ return {

this.select(next.element);
this.select(next.element, DIRECTION.right);
}
};
/**
* Navigate down to the next element if any.
*/
Navigator.prototype.down = function() {

@@ -209,5 +271,3 @@ if (!this.$selected) {

var next = this.elementsAfter(0, top).reduce(function(prev, curr) {
curr = $(curr);
var currDistance = curr.position();
currDistance = Math.abs(currDistance.left - left) + Math.abs(currDistance.top - top);
var currDistance = Math.abs(curr.offsetLeft - left) + Math.abs(curr.offsetTop - top);
if (currDistance < prev.distance) {

@@ -224,6 +284,11 @@ return {

this.select(next.element);
this.select(next.element, DIRECTION.down);
}
};
/**
* Return the selected DOM element.
*
* @return {Element} The selected DOM element.
*/
Navigator.prototype.selected = function() {

@@ -233,24 +298,92 @@ return this.$selected;

Navigator.prototype.select = function(element) {
if (element && element !== this.$selected) {
// Unbox element from jQuery or array.
if (element.jquery || Array.isArray(element)) {
element = element[0];
/**
* Select the given element.
*
* @param el {Element} The DOM element to select.
*
* @return void
*/
Navigator.prototype.select = function(el, direction) {
// Is there an element or is it selected?
if (!el || el === this.$selected) {
return; // Nothing to do here.
}
el = unboxElement(el);
// Unselect previous element.
if (this.$selected) {
removeClass(this.$selected, this.$options.selected);
}
// Scroll to given element.
this.scrollTo(el, direction);
// Select given element.
addClass(el, this.$options.selected);
this.$selected = el;
};
/**
* Scroll the container to an element.
*
* @param el {Element} The destination element.
* @param direction {String} The direction of the current navigation.
*
* @return void.
*/
Navigator.prototype.scrollTo = function(el, direction) {
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;
}
// Unselect previous element.
if (this.$selected) {
removeClass(this.$selected, this.$options.selected);
}
// Select given element.
addClass(element, this.$options.selected);
this.$selected = element;
}
};
/**
* Indicate if an element is in the container viewport.
*
* @param el {Element} The element to check.
*
* @return {Boolean} true if the given element is in the container viewport, otherwise false.
*/
Navigator.prototype.inContainerViewport = function(el) {
el = unboxElement(el);
// Check on left side.
if (el.offsetLeft - this.$container.scrollLeft < this.$container.offsetLeft) {
return false;
}
// Check on top side.
if (el.offsetTop - this.$container.scrollTop < this.$container.offsetTop) {
return false;
}
// Check on right side.
if ((el.offsetLeft + el.offsetWidth - this.$container.scrollLeft) > (this.$container.offsetLeft + this.$container.offsetWidth)) {
return false;
}
// Check on down side.
if ((el.offsetTop + el.offsetHeight - this.$container.scrollTop) > (this.$container.offsetTop + this.$container.offsetHeight)) {
return false;
}
return true;
};
/**
* Return an array of the navigable elements.
*
* @return {Array} An array of elements.
*/
Navigator.prototype.elements = function() {
var children = [];
for (var i = this.$element.children.length; i--;) {
for (var i = this.$container.children.length; i--;) {
// Skip comment nodes on IE8
if (this.$element.children[i].nodeType !== 8) {
children.unshift(this.$element.children[i]);
if (this.$container.children[i].nodeType !== 8) {
children.unshift(this.$container.children[i]);
}

@@ -261,2 +394,10 @@ }

/**
* Return an array of navigable elements after an offset.
*
* @param left {Integer} The left offset.
* @param top {Integer} The top offset.
*
* @return {Array} An array of elements.
*/
Navigator.prototype.elementsAfter = function(left, top) {

@@ -268,2 +409,10 @@ return this.elements().filter(function(el) {

/**
* Return an array of navigable elements before an offset.
*
* @param left {Integer} The left offset.
* @param top {Integer} The top offset.
*
* @return {Array} An array of elements.
*/
Navigator.prototype.elementsBefore = function(left, top) {

@@ -275,2 +424,9 @@ return this.elements().filter(function(el) {

/**
* Handle the keydown event.
*
* @param {Event} The event object.
*
* @return void.
*/
Navigator.prototype.handleKeydown = function(event) {

@@ -277,0 +433,0 @@ if (this.$keys[event.which]) {

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

/*! dom-navigator - v1.0.0 - 2014-08-13
/*! dom-navigator - v1.0.1 - 2014-08-16
* https://github.com/rmariuzzo/dom-navigator
* Copyright (c) 2014 Rubens Mariuzzo; Licensed MIT */
!function(a){"function"==typeof define&&define.amd?define([],function(){return a(jQuery)}):a(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")," ")}var e=function(a,c){this.$doc=window.document,this.$element=a,this.$options=b({},e.defaults,c),this.$selected=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.$keydownHandler=null,this.enable()};if(e.defaults={selected:"selected",left:37,up:38,right:39,down:40},e.prototype.enable=function(){var a=this;this.$keydownHandler=function(b){a.handleKeydown.call(a,b)},this.$doc.addEventListener("keydown",this.$keydownHandler)},e.prototype.disable=function(){this.$keydownHandler&&this.$doc.removeEventListener("keydown",this.$keydownHandler)},e.prototype.destroy=function(){this.disable(),this.$element.domNavigator&&delete this.$element.domNavigator},e.prototype.left=function(){if(this.$selected){var b=this.$selected.offsetLeft-1,c=this.$selected.offsetTop,d=this.elementsBefore(b,1/0).reduce(function(d,e){e=a(e);var f=e.position();return f=Math.abs(b-f.left)+Math.abs(c-f.top),f<d.distance?{distance:f,element:e}:d},{distance:1/0});this.select(d.element)}else this.select(this.elements()[0])},e.prototype.up=function(){if(this.$selected){var b=this.$selected.offsetLeft,c=this.$selected.offsetTop-1,d=this.elementsBefore(1/0,c).reduce(function(d,e){e=a(e);var f=e.position();return f=Math.abs(b-f.left)+Math.abs(c-f.top),f<d.distance?{distance:f,element:e}:d},{distance:1/0});this.select(d.element)}else this.select(this.elements()[0])},e.prototype.right=function(){if(this.$selected){var b=this.$selected.offsetLeft+this.$selected.offsetWidth,c=this.$selected.offsetTop,d=this.elementsAfter(b,0).reduce(function(d,e){e=a(e);var f=e.position();return f=Math.abs(f.left-b)+Math.abs(f.top-c),f<d.distance?{distance:f,element:e}:d},{distance:1/0});this.select(d.element)}else this.select(this.elements()[0])},e.prototype.down=function(){if(this.$selected){var b=this.$selected.offsetLeft,c=this.$selected.offsetTop+this.$selected.offsetHeight,d=this.elementsAfter(0,c).reduce(function(d,e){e=a(e);var f=e.position();return f=Math.abs(f.left-b)+Math.abs(f.top-c),f<d.distance?{distance:f,element:e}:d},{distance:1/0});this.select(d.element)}else this.select(this.elements()[0])},e.prototype.selected=function(){return this.$selected},e.prototype.select=function(a){a&&a!==this.$selected&&((a.jquery||Array.isArray(a))&&(a=a[0]),this.$selected&&d(this.$selected,this.$options.selected),c(a,this.$options.selected),this.$selected=a)},e.prototype.elements=function(){for(var a=[],b=this.$element.children.length;b--;)8!==this.$element.children[b].nodeType&&a.unshift(this.$element.children[b]);return a},e.prototype.elementsAfter=function(a,b){return this.elements().filter(function(c){return c.offsetLeft>=a&&c.offsetTop>=b})},e.prototype.elementsBefore=function(a,b){return this.elements().filter(function(c){return c.offsetLeft<=a&&c.offsetTop<=b})},e.prototype.handleKeydown=function(a){this.$keys[a.which]&&(a.preventDefault(),this.$keys[a.which].call(this))},window.DomNavigator=e,a){var f=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 e(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=e,a.fn.domNavigator.noConflict=function(){return a.fn.domNavigator=f,this}}});
!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}var f=function(a,c){this.$doc=window.document,this.$container=a,this.$options=b({},f.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()};f.defaults={selected:"selected",left:37,up:38,right:39,down:40};var g={left:"left",up:"up",right:"right",down:"down"};if(f.prototype.enable=function(){var a=this;this.$keydownHandler=function(b){a.handleKeydown.call(a,b)},this.$doc.addEventListener("keydown",this.$keydownHandler)},f.prototype.disable=function(){this.$keydownHandler&&this.$doc.removeEventListener("keydown",this.$keydownHandler)},f.prototype.destroy=function(){this.disable(),this.$container.domNavigator&&delete this.$container.domNavigator},f.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,g.left)}else this.select(this.elements()[0])},f.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,g.up)}else this.select(this.elements()[0])},f.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,g.right)}else this.select(this.elements()[0])},f.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,g.down)}else this.select(this.elements()[0])},f.prototype.selected=function(){return this.$selected},f.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)},f.prototype.scrollTo=function(a,b){if(!this.inContainerViewport(a))switch(b){case g.left:break;case g.up:this.$container.scrollTop=a.offsetTop-this.$container.offsetTop;break;case g.right:break;case g.down:this.$container.scrollTop=a.offsetTop-this.$container.offsetTop-(this.$container.offsetHeight-a.offsetHeight)}},f.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},f.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},f.prototype.elementsAfter=function(a,b){return this.elements().filter(function(c){return c.offsetLeft>=a&&c.offsetTop>=b})},f.prototype.elementsBefore=function(a,b){return this.elements().filter(function(c){return c.offsetLeft<=a&&c.offsetTop<=b})},f.prototype.handleKeydown=function(a){this.$keys[a.which]&&(a.preventDefault(),this.$keys[a.which].call(this))},window.DomNavigator=f,a){var h=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 f(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=f,a.fn.domNavigator.noConflict=function(){return a.fn.domNavigator=h,this}}});
{
"name": "dom-navigator",
"version": "1.0.0",
"version": "1.0.1",
"description": "Library that allow keyboard navigation through DOM elements (←↑→↓).",

@@ -5,0 +5,0 @@ "keywords": [

@@ -1,29 +0,73 @@

DOM Navigator
=============
# DOM Navigator
> Library that allow keyboard navigation through DOM elements (←↑→↓).
Installation
------------
## Installation
Using bower:
#### Bower
bower install domnavigator --save
```sh
bower install dom-navigator --save
```
Using NPM:
#### NPM
npm install domnavigator --save
```sh
npm install dom-navigator --save
```
Usage
=====
#### Manual
Vanilla JavaScript:
1. [Download the latest release](https://github.com/rmariuzzo/dom-navigator/releases).
2. Then include `dom-navigator-###.min.js` into your HTML page.
var el = document.querySelector('#grid');
var nav = new DomNavigator(el);
## Usage
#### Pure JavaScript
```js
var el = document.querySelector('#grid');
new DomNavigator(el);
```
#### jQuery
If jQuery is included you can use the library as a jQuery plugin:
var el = $('#grid');
el.domNavigator();
```js
var el = $('#grid');
el.domNavigator();
```
## Want to contribute?
All help are more than welcome!
#### Pre-requisites
- [Node.js](http://nodejs.org/).
- [Grunt](http://gruntjs.com/).
- [Bower](http://bower.io/).
#### Development Workflow
1. **[Fork](https://github.com/rmariuzzo/dom-navigator/fork)** this respository.
2. **Clone** your fork and create a feature branch from develop.
git clone git@github.com:<your-username>/dom-navigator.git
git fetch origin
git checkout develop
git checkout -b feature-<super-power>
3. **Install** development dependencies.
npm install
bower install
4. **Code** and be happy!
5. **Test** your code using QUnit `grunt test`.
6. Submit a **pull request** and grab popcorn.
### Credits
**dom-navigator** was created by [Rubens Mariuzzo](http://github.com/rmariuzzo) with all the love in the world.

@@ -16,7 +16,7 @@ /*

define([], function() {
return factory(jQuery);
return factory(window.jQuery);
});
} else {
// Browser globals
factory(jQuery);
factory(window.jQuery);
}

@@ -64,2 +64,16 @@

/**
* Unbox an object from jQuery or array.
*
* @param obj {Object} The object to unbox.
*
* @return {Element} An element.
*/
function unboxElement(obj) {
if (obj.jquery || Array.isArray(obj)) {
return obj[0];
}
return obj;
}
//-------------//

@@ -69,7 +83,16 @@ // Constructor //

var Navigator = function(element, options) {
/**
* Create a new DOM Navigator.
*
* @param container {Element} The container of the element to navigate.
* @param options {Object} The options to configure the DOM navigator.
*
* @return void.
*/
var Navigator = function(container, options) {
this.$doc = window.document;
this.$element = element;
this.$container = container;
this.$options = extend({}, Navigator.defaults, options);
this.$selected = null;
this.$keydownHandler = null;
this.$keys = {};

@@ -80,6 +103,8 @@ this.$keys[this.$options.left] = this.left;

this.$keys[this.$options.down] = this.down;
this.$keydownHandler = null;
this.enable();
};
/**
* Defaults options.
*/
Navigator.defaults = {

@@ -93,2 +118,12 @@ selected: 'selected',

/**
* Direction constants.
*/
var DIRECTION = {
left: 'left',
up: 'up',
right: 'right',
down: 'down'
};
//---------//

@@ -98,2 +133,7 @@ // Methods //

/**
* Enable this navigator.
*
* @return void.
*/
Navigator.prototype.enable = function() {

@@ -107,2 +147,7 @@ var self = this;

/**
* Disable this navigator.
*
* @return void.
*/
Navigator.prototype.disable = function() {

@@ -114,9 +159,19 @@ if (this.$keydownHandler) {

/**
* Destroy this navigator removing any event registered and any other data.
*
* @return void.
*/
Navigator.prototype.destroy = function() {
this.disable();
if (this.$element.domNavigator) {
delete this.$element.domNavigator;
if (this.$container.domNavigator) {
delete this.$container.domNavigator;
}
};
/**
* Navigate left to the next element if any.
*
* @return void.
*/
Navigator.prototype.left = function() {

@@ -130,5 +185,3 @@ if (!this.$selected) {

var next = this.elementsBefore(left, Infinity).reduce(function(prev, curr) {
curr = $(curr);
var currDistance = curr.position();
currDistance = Math.abs(left - currDistance.left) + Math.abs(top - currDistance.top);
var currDistance = Math.abs(left - curr.offsetLeft) + Math.abs(top - curr.offsetTop);
if (currDistance < prev.distance) {

@@ -145,6 +198,11 @@ return {

this.select(next.element);
this.select(next.element, DIRECTION.left);
}
};
/**
* Navigate up to the next element if any.
*
* @return void.
*/
Navigator.prototype.up = function() {

@@ -158,5 +216,3 @@ if (!this.$selected) {

var next = this.elementsBefore(Infinity, top).reduce(function(prev, curr) {
curr = $(curr);
var currDistance = curr.position();
currDistance = Math.abs(left - currDistance.left) + Math.abs(top - currDistance.top);
var currDistance = Math.abs(left - curr.offsetLeft) + Math.abs(top - curr.offsetTop);
if (currDistance < prev.distance) {

@@ -173,6 +229,11 @@ return {

this.select(next.element);
this.select(next.element, DIRECTION.up);
}
};
/**
* Navigate right to the next element if any.
*
* @return void.
*/
Navigator.prototype.right = function() {

@@ -186,5 +247,3 @@ if (!this.$selected) {

var next = this.elementsAfter(left, 0).reduce(function(prev, curr) {
curr = $(curr);
var currDistance = curr.position();
currDistance = Math.abs(currDistance.left - left) + Math.abs(currDistance.top - top);
var currDistance = Math.abs(curr.offsetLeft - left) + Math.abs(curr.offsetTop - top);
if (currDistance < prev.distance) {

@@ -201,6 +260,9 @@ return {

this.select(next.element);
this.select(next.element, DIRECTION.right);
}
};
/**
* Navigate down to the next element if any.
*/
Navigator.prototype.down = function() {

@@ -214,5 +276,3 @@ if (!this.$selected) {

var next = this.elementsAfter(0, top).reduce(function(prev, curr) {
curr = $(curr);
var currDistance = curr.position();
currDistance = Math.abs(currDistance.left - left) + Math.abs(currDistance.top - top);
var currDistance = Math.abs(curr.offsetLeft - left) + Math.abs(curr.offsetTop - top);
if (currDistance < prev.distance) {

@@ -229,6 +289,11 @@ return {

this.select(next.element);
this.select(next.element, DIRECTION.down);
}
};
/**
* Return the selected DOM element.
*
* @return {Element} The selected DOM element.
*/
Navigator.prototype.selected = function() {

@@ -238,24 +303,92 @@ return this.$selected;

Navigator.prototype.select = function(element) {
if (element && element !== this.$selected) {
// Unbox element from jQuery or array.
if (element.jquery || Array.isArray(element)) {
element = element[0];
/**
* Select the given element.
*
* @param el {Element} The DOM element to select.
*
* @return void
*/
Navigator.prototype.select = function(el, direction) {
// Is there an element or is it selected?
if (!el || el === this.$selected) {
return; // Nothing to do here.
}
el = unboxElement(el);
// Unselect previous element.
if (this.$selected) {
removeClass(this.$selected, this.$options.selected);
}
// Scroll to given element.
this.scrollTo(el, direction);
// Select given element.
addClass(el, this.$options.selected);
this.$selected = el;
};
/**
* Scroll the container to an element.
*
* @param el {Element} The destination element.
* @param direction {String} The direction of the current navigation.
*
* @return void.
*/
Navigator.prototype.scrollTo = function(el, direction) {
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;
}
// Unselect previous element.
if (this.$selected) {
removeClass(this.$selected, this.$options.selected);
}
// Select given element.
addClass(element, this.$options.selected);
this.$selected = element;
}
};
/**
* Indicate if an element is in the container viewport.
*
* @param el {Element} The element to check.
*
* @return {Boolean} true if the given element is in the container viewport, otherwise false.
*/
Navigator.prototype.inContainerViewport = function(el) {
el = unboxElement(el);
// Check on left side.
if (el.offsetLeft - this.$container.scrollLeft < this.$container.offsetLeft) {
return false;
}
// Check on top side.
if (el.offsetTop - this.$container.scrollTop < this.$container.offsetTop) {
return false;
}
// Check on right side.
if ((el.offsetLeft + el.offsetWidth - this.$container.scrollLeft) > (this.$container.offsetLeft + this.$container.offsetWidth)) {
return false;
}
// Check on down side.
if ((el.offsetTop + el.offsetHeight - this.$container.scrollTop) > (this.$container.offsetTop + this.$container.offsetHeight)) {
return false;
}
return true;
};
/**
* Return an array of the navigable elements.
*
* @return {Array} An array of elements.
*/
Navigator.prototype.elements = function() {
var children = [];
for (var i = this.$element.children.length; i--;) {
for (var i = this.$container.children.length; i--;) {
// Skip comment nodes on IE8
if (this.$element.children[i].nodeType !== 8) {
children.unshift(this.$element.children[i]);
if (this.$container.children[i].nodeType !== 8) {
children.unshift(this.$container.children[i]);
}

@@ -266,2 +399,10 @@ }

/**
* Return an array of navigable elements after an offset.
*
* @param left {Integer} The left offset.
* @param top {Integer} The top offset.
*
* @return {Array} An array of elements.
*/
Navigator.prototype.elementsAfter = function(left, top) {

@@ -273,2 +414,10 @@ return this.elements().filter(function(el) {

/**
* Return an array of navigable elements before an offset.
*
* @param left {Integer} The left offset.
* @param top {Integer} The top offset.
*
* @return {Array} An array of elements.
*/
Navigator.prototype.elementsBefore = function(left, top) {

@@ -280,2 +429,9 @@ return this.elements().filter(function(el) {

/**
* Handle the keydown event.
*
* @param {Event} The event object.
*
* @return void.
*/
Navigator.prototype.handleKeydown = function(event) {

@@ -282,0 +438,0 @@ if (this.$keys[event.which]) {

@@ -80,2 +80,25 @@ (function($) {

module('jQuery#domNavigator("inContainerViewport", ...)', lifecycle);
test('exists', function() {
ok($.fn.domNavigator.Constructor.prototype.inContainerViewport, 'should exist');
});
test('should return expected values', function() {
var target = this.target;
var contTop = this.target.position().top;
var contBottom = contTop + this.target.height();
var contScroll = this.target.scrollTop();
this.target.children().each(function(i, el) {
el = $(el);
var elTop = el.position().top;
var elBottom = elTop + el.height();
var expected = elTop - contScroll >= contTop;
expected = expected && elBottom - contScroll <= contBottom;
ok(target.domNavigator("inContainerViewport", el) === expected, 'should return: ' + expected + ' for element: ' + el.text());
});
});
module('jQuery#domNavigator("left")', lifecycle);

@@ -82,0 +105,0 @@

@@ -78,2 +78,24 @@ (function($) {

module('DomNavigator.inContainerViewport()', lifecycle);
test('exists', function() {
ok(DomNavigator.prototype.inContainerViewport, 'should exist');
});
test('should return expected values', function() {
var domNavigator = this.domNavigator;
var contTop = this.target[0].offsetTop;
var contBottom = contTop + this.target[0].offsetHeight;
var contScroll = this.target[0].scrollTop;
this.target.children().each(function(i, el) {
var elTop = el.offsetTop;
var elBottom = elTop + el.offsetHeight;
var expected = elTop - contScroll >= contTop;
expected = expected && elBottom - contScroll <= contBottom;
ok(domNavigator.inContainerViewport(el) === expected, 'should return: ' + expected + ' for element: ' + el.textContent);
});
});
module('DomNavigator.left()', lifecycle);

@@ -80,0 +102,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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