luke-chang / js-spatial-navigation Goto Github PK
View Code? Open in Web Editor NEWA javascript-based implementation of Spatial Navigation.
License: Mozilla Public License 2.0
A javascript-based implementation of Spatial Navigation.
License: Mozilla Public License 2.0
Imported the js in my angular-cli.json
using
"scripts": [
"../path"
];
added declare var SpacialNavigation:any;
in typings.d.ts
and imported in my app.component.ts
as import * as SpacialNavigation from 'SpacialNavigation';
but the navigation doesn't work. any help?
I'm just confused... does that mean it'll pick the id of an element??? If that's how it's supposed to work well it doesn't work.....
Hi, thanks for this lovely library. I am trying to get this to work on a basic angular JS app. It doesn't look like it is able to detect focusable elements at all. I see the library being loaded, init being called, keydown handler being called, but it never finds a focusable entity.
I've set up a very simple codepen here https://codepen.io/pliablepixels/pen/odPpJX
Can you tell me if I am missing anything?
Thanks
It would be helpful if developers can install the module through Bower.
What are the minimum versions of angular,Npm,gulp & zone.js version required to run the spatial navigation? Currently our angular version was 4 and npm version was 7.10.
I need to upgrade my angular application for that specific version of various DLL dependencies which i need to modify in package.json file.How can i get exact dll version of various dependencies. Also which all files I need to take for the same.
Currently if anything is added as an external file in our application the files get automatically deleted. Can you suggest the reason behind this?
Hi, i tried to remove a element from being navigable using SpatialNavigation.remove("selector") but it doesnt seem to work at all. If i pause the nav though, that works but i just wanna remove and element from being navigable for a while.
Hi,
The focused element is losing focus when we click anywhere outside the html file. Is it possible to keep the focus even when the html page is not in focus or at least so the element highlighted?
If I click on the address bar the element loses focus and I am not sure which element has focus until I press the arrow keys.
I am facing focusing issue, I am able to navigate properly,but could not initiate a enter key event anywhere unless and until I click on button or anywhere on page with a mouse then only I am able to regain complete control, Please give me a solution, I am stuck.
Hi,
I'm using Spatial Navigation for TV based applications, and so far it works perfectly. However I recently encountered a bug that's rather weird.
I've pinned it down to using ".focus" to focus an element.
First things first however: It's important to know this is an HbbTV/SmartTVA environment. The platform is "OperaTV" (Based on opera V31 with a chrome 44 core.) it's easy enough to replicate, by downloading the "Vewd TV emulator" (Which is where I first noticed it happening), this bug does NOT manifest itself in modern desktop browsers, including browsers using the HbbTV browser add-on to emulate a HbbTV device.
I'm afraid I can't take screen shots of the output, as the actual display output is on a device separate to the machine I code and am typing this on, I will describe it as best I can however.
I'm actually able to attach the full HTML app to this bug report, as it's all in one file
index.zip
Existentially the main HTML in the doc are these two lines:
<div id="appsBar" class=""></div>
<object id="video" type="" ></object>
The appsBar div element is filled with a series of inner divs, representing application icons that can be selected using up/down/enter, it's this navigation that the spatial library is used for.
when the div is populated, and "SpatialNavigation" has been set up, made focusable etc, the appsBar looks as follows
<div id="appsBar" class="showBar">
<div id="app0" class="appIcon focusable" data-url="http://www.bbc.co.uk/newsontal" data-name="BBC News" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/bbc-news.png"></div>
<div id="app1" class="appIcon focusable" data-url="http://www.bbc.co.uk/sprtiptvjs" data-name="BBC Sports" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/bbc-sports.png"></div>
<div id="app2" class="appIcon focusable" data-url="https://www.live.bbctvapps.co.uk/tap/iplayer" data-name="BBC iPlayer" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/bbc-iplayer.png"></div>
<div id="app3" class="appIcon focusable" data-url="https://www.youtube.com/tv" data-name="YouTube" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/youtube.png"></div>
<div id="app4" class="appIcon focusable" data-url="http://plex.tv/web/tv/opera?origin=TV%20Store%201" data-name="Plex" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/plex.png"></div>
<div id="app5" class="appIcon focusable" data-url="http://192.168.17.214:8096/" data-name="Emby" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/emby.png"></div>
<div id="app6" class="appIcon focusable" data-url="https://vestel.chili.tv" data-name="Chili TV" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/chili.png"></div>
<div id="app7" class="appIcon focusable" data-url="http://nettv.cinetrailer.tv/foxxum-ant/region.asp" data-name="Cinetrailer" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/cinetrailer.png"></div>
<div id="app8" class="appIcon focusable" data-url="https://vestel.tvstore.opera.com" data-name="Vewd" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/vewd.png"></div>
<div id="app9" class="appIcon focusable" data-url="http://www.google.com" data-name="Google" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/google.png"></div>
<div id="app10" class="appIcon focusable" data-url="browser://open" data-name="Browser" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/open-browser_v2.png"></div>
<div id="app11" class="appIcon focusable" data-url="http://itv.mit-xperts.com/hbbtvtest/" data-name="HbbTVTest" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/default.png"></div>
<div id="app12" class="appIcon focusable" data-url="http://immosmart.github.io/smartbox/demo/demoApp" data-name="ShawtyTest" tabindex="-1"><span class="verticalCenterHelper"></span><img src="/images/logos/default.png"></div>
</div>
The CSS rule for the app bar places it off screen on the right hand side of the display, and pressing the red button add's a new part to the rule that slides the bar into view.
Initially I disable the spatial navigation on the appsBar and when it comes into view I enable it. Likewise when it disappears from view I disable the navigation on the appsBar once more, so that nothing can be triggered accidentally.
As you should be able to see in the attached file (at around line 210), when I open the bar I also set focus to the first element in the appsBar:
SpatialNavigation.focus("#app0", false);
When I do this, the other object on the page (An OIPF broadcast video object) flicks to the left hand side of the screen, then transitions back (It actually does a number of other things depending on where on the screen it is and what it's size is), as this element is NOT part of any navigation in the application, then this should not be moving or animating or anything like that.
The video object is fine and remains untouched if I take out the "focus" call, and I've also tried using 'true' in the silence parameter too, which makes no difference.
I need to always switch focus to the first item on my appsBar when it's opened, but I need to be able to do so without the video being moved.
The video object when fully initialized actually sits in the background and displays the broadcast video stream coming in from the devices reception, and so must remain still.
The appsBar is intended to slide in and out from the right allowing the TV user to select a different application to run.
@luke-chang i am having a small issue when using this code i am pulling new eliments into dom using a json request and then making them focusable using SN.makeFocusable();
my issue is that when i click the enter key on the newly populated eliments it does not run the code to grab the id and run the appropriate code i have double checked this by doing the following
setting a default eliment clicking on it and javascript alert shows and then inner html is cleared and then the same default eliment is reappended and SN.makeFocusable(); is run again i can then navigate back to this default eliment but click on it does not run the function to show the alert even tho it worked when loaded with the page initially so any eliments loaded to dom after the initial page load and able to be navigated but cant be clicked
Please Help
I have a html structure like this:
<div id='home' class='b-content home'>
<div class='col-md-4 col-sm-4 col-xs-12'>
<a href='link1.php' class='focusable'>
<div class='col-md-12'>
<center><img src='img/icon1.png'></center>
<h3 class='text-center'>Link 1</h3>
</div>
</a>
</div>
<div class='col-md-4 col-sm-4 col-xs-12'>
<a href='link2.php' class='test focusable'>
<div class='col-md-12'>
<center><img src='img/icon2.png'></center>
<h3 class='text-center'>Link 2</h3>
</div>
</a>
</div>
<div class='col-md-4 col-sm-4 col-xs-12'>
<a href='link3.php' class='focusable'>
<div class='col-md-12'>
<center><img src='img/icon3.png'></center>
<h3 class='text-center'>Link 3</h3>
</div>
</a>
</div>
<div class='col-md-8 col-sm-12 col-xs-12 Mybtns'>
<div class='col-md-4 col-sm-12 col-xs-12'>
<a class='focusable btn btn-default center-block btn-lg account' href='#'>
<i class='fa fa-info'></i> Link 4</a>
</div>
<div class='col-md-4 col-sm-12 col-xs-12'>
<a class='btn btn-default center-block btn-lg account focusable' href='link4.php'>
<i class='fa fa-clock-o' >
</i> Link 5</a>
</div>
<div class='col-md-4 col-sm-12 col-xs-12'>
<a href='' class='btn btn-default center-block btn-lg'>
<i class='fa fa-sign-out' style='padding-top: 0px;'>
</i> Link 6</a>
</div>
</div>
Its not working and I cant navigate between blocks. If I put the "a" links outside of div its working fine but its broke all my application links and styles.
How can I navigate with this structure?
I have a feeling I may already know the answer to this question after a perusal through all of the documentation but are there any links or methodology related to a back button for this library?
When an input text element receives focus, the left and right arrow keys as well as the "enter" button are unresponsive.
That is, you cannot move the cursor left or right. It is also not possible to "confirm" the text entered by pressing the "enter" key.
i need to run a some jquery code when a focused eliment is proessed
Hi,
Spatial navigation is not working on Microsoft Web Apps. I assume it's because you navigate using gamepad and keycodes triggering nav are different.
Any chances to get a feature where we could define keycodes for keys triggering navigation?
I have a page with Some text as header and then some focusable button items in the rest of the page. Issue I'm facing is when I navigate (using keyboard keys and not mouse) through the page my Page doesn't scroll to the header part (because the header is not a focusable item).
I'm wondering whether is there a way I can scroll the page (through the Up key on keyboard) to the top (to the header) even if there's not focusable items on top of the page?
Here's some sample code (modified code of demo example 1.4_basic_config.html to have header and footer)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>JavaScript SpatialNavigation Demo Page</title>
<link rel="stylesheet" href="css/style_1.css">
<script src="../spatial_navigation.js"></script>
<script>
window.addEventListener('load', function() {
SpatialNavigation.init();
// We can add some configurations when initializing a section.
SpatialNavigation.add({
selector: '.focusable',
// Give it an id so we can identify it later.
id: 'main',
// Limit the navigating direction to vertical and horizontal only.
// Targets in oblique (left-top, right-top, left-bottom, and
// right-bottom) directions are always ignored.
straightOnly: true,
// This threshold is used to determine whether an element is
// considered in straight (vertical or horizontal) directions. Valid
// number is between 0 to 1.0. Setting it to 0.3 means an element is
// counted in the straight directions if it overlaps the straight area
// at least 0.3x of width of the area.
straightOverlapThreshold: 0.5,
// The previous focused element has high priority to be chosen as the
// next candidate.
rememberSource: true
});
SpatialNavigation.makeFocusable();
SpatialNavigation.focus();
[].slice.call(document.querySelectorAll('input[type="checkbox"]'))
.forEach(function(elem) {
elem.checked = true;
elem.addEventListener('change', function(evt) {
var config = {};
config[this.value] = this.checked;
// You can change the configurations of the specified section at
// runtime. If section id is omitted, the global configurations
// will be changed.
SpatialNavigation.set('main', config);
});
});
});
</script>
</head>
<body>
<!-- <div class="focusable" tabindex="-1" style="background-color: black; width: 100%; height: 100px;"></div> -->
<div style="background-color: black; width: 100%; height: 100px;"></div>
<div id="container">
<div class="leftbox">
<div class="focusable"></div>
<div class="focusable"></div>
<div class="focusable"></div>
<div class="focusable"></div>
<div class="nonfocusable"></div>
</div>
<div class="rightbox">
<div id="main" class="focusable"></div>
<div class="bottombox">
<div class="focusable"></div>
<div class="focusable"></div>
<div class="focusable"></div><br>
<div class="focusable"></div>
<div class="focusable"></div>
<div class="focusable"></div>
</div>
</div>
</div>
<div id="sidebox" tabindex="-1">
Config:
<label><input type="checkbox" name="config" value="straightOnly"> straightOnly</label>
<label><input type="checkbox" name="config" value="rememberSource"> rememberSource</label>
</div>
<div style="background-color: black; width: 100%; height: 100px;"></div>
</body>
</html>
In the above code when navigated through top and bottom arrow keys you can notice that header/footer part (black line) is not visible as the scroll doesn't go to top/bottom of the page.
One workaround is to make the header / footer part div tag as focusable. But, there could be scenarios where this is not possible always (for ex. if top/bottom of the page is just an empty space). So I'm wondering whether there can be any other solution to emable the scroll (through up/down arrow keys) to go completely to top/bottom of the page when navigated through arrow keys.
I want to create something like youtube.tv
In the youtube app, in horizontal navigation, the active element alway stay on left or "Almost" in the middle of the window. How can we recreate this?
https://www.youtube.com/tv
I have an iframe in my application and I have access to both the parent and child applications so I can choose the selectors wisely. But SpatialNavigation doesn't work if I navigate it either from parent or child. is there anyway I could do it?
Hi.
I'd like to know which version of the Mozilla Public License this project is licensed under. (there are several)
Cheers!
Youtube Demo - do not go up or down if there's nothing directly above or below
In the Youtube demo, You can go up or down if there's nothing right or straight above or below, How can we fix this?
In my exemple, if you go on the first contentgroup and navigate to the last item to the right, you can not go up to search box. It also happen on your Youtube demo. if you go to the last item, you can not go down or up to the next content group if there's nothing straight foward, it even jump to the second contengroup.
And it do not remember the last elment focused when we navigate up and down between .contentgroup
http://tvcast.top/scripts/js-spatial-navigation-master/demo/apptv.html
By the way, i created a demo based on smart TV, you simply add .scrollX class to .content for overflow scroll horizontally and keep the focus item in the center.
add .scale class to #content to create a scale effect.
Here without the .scall class
http://tvcast.top/scripts/js-spatial-navigation-master/demo/1-YT-TV.html
I think there's something to do with this, may be a open project for javascript hybride TV Apps, web app, Android & IOS apps, Roku, Apple TV, Smart TV, X-box ect.
How can i implement and add mousewheel navigation with spatial navigation?
May be with this jQuery plugin
https://plugins.jquery.com/mousewheel/
https://stackoverflow.com/questions/29652911/catch-mousewheel-up-or-down-with-jquery-js-without-actually-scrolling/29656088#29656088
Hi, I would like to have a demo for a page having a couple of dropdowns and somme buttons.
I have been able to develop a small test site using your code http://loopzine.tv/firetv.htm
just one persistent problem. My links open a new page to play mpeg4 videos when I use the return or back button on the fireTV d-pad my home page defaults to the first focusable element on the page instead of the last focused element. I think its working as expected on my windows chrome browser but not on the firetv???
Hi!
Could you add possibility to call focus with { preventScroll: true }
?
I create a website that can be navigable from the keyboard.
Everything work well with my keyboard navigation with this navigation plugin but after hours and days i still can't navigate these Video js buttons and i don't understand why.
I did a little example here one Codepen and it still not working.
https://codepen.io/onigetoc/pen/MWBowmg
I use the videojs seek plugin to add a forward and rewind buttons.
I will also use the videojs hotkeys plugin but for now, i'm just trying to make my player navigable with the arrow keyboard.
I absolutely want to use the Spatial Navigation plugin.
Feature request
When sn:willmove
events are originated by key presses (i.e e.detail.cause === 'keydown'
), it would be nice to know what value the original event's repeat
flag had.
var willmoveProperties = {
direction: direction,
sectionId: currentSectionId,
cause: 'keydown',
repeat: evt.repeat // this is everything we need to add
};
I would love to have this information available on all events, but this is the simplest one to implement. Also, whether or not this makes sense for focus-related events might need some discussion, while here fits pretty nicely.
I can prepare a PR if needed.
Would be great if developers can install the module through NPM.
I tried using it with webos sdk (while developing application for webos, you are developing with html css and js), I didn't get any error in console but navigation didn't work at all. Can you help?
I am creating a browser for accessibility and am using your spatial navigation to make the pages navigable with keyboard. I am able to inject your JavaScript code for the onload event of the first website added to my browser and the navigation works fine. For subsequent link clicks in that page I am not able to inject your JavaScript code and hence the spatial navigation is not working. How to make the spatial navigation to work in all pages? (even for pages opened by clicking on the links in the first page).
Hi Luke,
How can I check the current element is the last item? I want to remove all focusable class in the list TV and add new focusable class to the left menu and reinitialize for this menu?
Take a look at my site plz: http://tv.beeb.vn
Thanks!
I am thinking of having arrow buttons on screen instead of navigating with keyboard keys. Can you suggest me some method to achieve this.
It would be nice to have a basic sample usage in the README file.
The NPM metadata at https://www.npmjs.com/package/spatial-navigation-js claims the license is ISC (which is a very permissive license) but the project actually has an MPL-2.0 (copyleft) license. Can you update one or the other so that they are consistent?
It would be great to have those demos published so people can access without cloning.
I am working on a web application for smart TV , i find it difficult to get the focus on element i create with data that gets rendered from the api. I believe only rendered elements or already available elements are focused right now for my application. Also i am using pure JavaScript with no framework for my app, can you please help me on this ?
Hello,
I can't get the "enterTo: last-focused" property to work on my application based on Youtube like demo.
Indeed, when I change section, the focus is positioned directly on the horizontal element.
Can you please help me?
Thank you in advance.
https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus
would also be nice to have a way to get a list of active sections
The defaultElement
is not working properly.
According to the documentation about defaultElement :
the first element matching defaultElement within this section will be chosen first.
However in the source code, into spatial_navigation.js -> function getSectionDefaultElement, l. 561 :
if (typeof defaultElement === 'string') {
defaultElement = parseSelector(defaultElement)[0];
}
The default element is indeed the first element matching the selector but the first element is not necessarily within the targeted section.
Example with this sample :
<div id="section1" class="focusable">
<button class="target" >Button 1</button>
<button>Button 2</button>
<button>Button 3</button>
</div>
<div id="section2" class="focusable">
<button class="target">Button 4</button>
<button>Button 5</button>
<button>Button 6</button>
</div>
And for section2 the following configuration :
var conf = {
enterTo: 'default-element',
defaultElement: '.target'
}
In this case, parseSelector(defaultElement)[0]
will return the <button class="target" >Button 1</button>
element because the selector is .target
. But this element is not within section2 so it will not be focused but the source code does not check if other elements returned by parseSelector(defaultElement)
is within the targeted section.
Edit - 04/01/2022
A simple way to fix it :
function getSectionDefaultElement(sectionId) {
var defaultElement = _sections[sectionId].defaultElement;
if (!defaultElement) {
return null;
}
if (typeof defaultElement === 'string') {
// defaultElement = parseSelector(defaultElement)[0]; // bug !
var elements = parseSelector(defaultElement);
// check each element to see if it's navigable and stop when one has been found
for (var element of elements) {
if (isNavigable(element, sectionId, true)) {
return element;
}
}
return null;
} else if ($ && defaultElement instanceof $) {
defaultElement = defaultElement.get(0);
if (isNavigable(defaultElement, sectionId, true)) {
return defaultElement;
}
}
return null;
}
If it is the normal behavior then change the documentation about defaultElement
by something like that:
When a section is specified to be the next focused target, e.g. focus('some-section-id') is called, the first element matching defaultElement within this section will be chosen first (warning : the given selector must concern elements exclusively within this section).
Hello,
Just a quick question. If I was to add an element to the DOM that I wanted to be focusable with the correct class, what should I call to update the focusable elements that SpatialNavigation knows about?
Thank you.
Hello,
Let's see my site: http://tv.beeb.vn/logos . And try press Shift + key down (arrow down) . Very choppy . How can I improve it?
Thanks!
to make it easier to experiment on jsfiddle, it might be worth to host a version on https://cdnjs.com/
Hi @luke-chang , how to keep two elements on focus ? suppose i select an item from menu, sub-menu to that item opens, i want to keep menu item highlighted/focused as long as i get a key event from sub-menu item. Is there a way to keep both menu and sub-menu item focused ??
Thanks,
zubeer
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.