HTML: show movement when tabbing between inputs? - javascript

I have a web app I would like to be controllable from the keyboard.
I recently saw a library that showed movement of the blue outline when tabbing between form fields. Eg, starting with the field 'one' highlighted:
[one]
another
Then when tab is hit:
one
[ ]
another
then finishing:
one
[another]
As you can see, it where the focus is moving to quite obvious for keyboard users.
The bad news: I can't find this library more, or anything like it. So my question:
Is there a tool to show movement during field focus changes like this? and, more to the point, where is it?
EDIT: Be a little more explicit: no, I really do not want make newly selected fields have an animated border.

The effect is called Focus Transition, and the library is called Flying Focus.

Actually it's not very hard effect (depends on conditions, of course), if i understand you correct.
Just create a 'dummy' hidden outline object in css and attach handler on focus event to all inputs you need and move your outline as you want in attached handler
For example with jQuery (written right here, may not work):
var $outline = $('#outline');
var padding = 6;
$('input').focus(function () {
var width = parseInt($(this).width()) + padding;
var height = parseInt($(this).height()) + padding;
var top = $(this).parent().offset()['top'] - padding/2;
var left = $(this).parent().offset()['left'] - padding/2;
$outline.stop().animate({
top: top,
top: top,
width: width,
left: left
});
});
You can try this fiddle (http://jsfiddle.net/C4Gde/) with something similar

Related

How to increase speed of mousemove/clientX/Y and applying a transform?

I have built a WordPress theme. I came across a website that created a div to follow the user's cursor. The div was enlarged smoothly when the user hovers over a button or a link.
I want to add this nice functionality as an optional feature.
I added a div to the web page, #ambition_cursor and added some basic styling. The div now shows like a blue circle. The circle has position fixed to the top left corner of the site. The position can be changed by adding a CSS translate property.
I managed to make it work with the following code:
var ambition_cursor = document.getElementById("ambition_cursor");
function ambition_mouse(e) {
var ambition_cursor_x = e.clientX; // Get the horizontal coordinate
var ambition_cursor_y = e.clientY; // Get the vertical coordinate
var ambition_cursor_pos = `translate(${ambition_cursor_x}px, ${ambition_cursor_y}px)`;
ambition_cursor.style.transform = ambition_cursor_pos;
}
window.addEventListener('mousemove', ambition_mouse);
The big downside here is the lag (?). There's quite a big delay, especially when moving the mouse around very fast. You can try it out on this site. I also put the situation in a JSFiddle; although the delay doesn't really happen there.
I didn't apply yet much styling (the default cursor is visible, so you can get a better idea of the real position). I first want this to work better, before I spent much time on that.
How can I increase the speed of this, so that the div position follows the mouse more accurately? I'm a beginner, so I don't really know which JavaScript optimisations I should make.
Current code is JavaScript, but jQuery is also an option.
Many thanks in advance!
Update: example how it looks on my computer.
All elements on the page have a transition applied. Remove/override this style and the delay goes away (tested).
As an alternative to the great answer of Joseph Atkinson:
var ambition_cursor = document.getElementById("ambition_cursor");
function ambition_mouse(e) {
ambition_cursor.style.left = e.clientX + 'px'; // Get the horizontal coordinate
ambition_cursor.style.top = e.clientY + 'px' ; // Get the vertical coordinate
}
window.addEventListener('mousemove', ambition_mouse);
See: https://levelup.gitconnected.com/use-javascript-to-make-an-element-follow-the-cursor-3872307778b4
I visited the site example, cracked open the dev console, and found throttled(20, ambition_mouse) It is not a performance issue, and the solution is to not throttle the events. It was too smooth to be a performance issue, which gave me the first clue it had to be an accidental/deliberate effect.

jQuery UI sortable - overlapping by 50% doesn't seem to work

jQuery UI sortable plugin is intended to enable a group of DOM elements to be sortable. A nice demo is at official website here
The API documentation provides tolerance option, and the description says:
Specifies which mode to use for testing whether the item being moved is hovering over another item. Possible values: intersect, pointer
Furthermore, the description of intersect (which is default) states:
intersect: The item overlaps the other item by at least 50%.
I expected, that if I drag one item, and move it over another item, it will detect that I'm reordering the items as soon as 50% of the height overlaps. But it doesn't seem to work this way :(. Even if you check the official demo, and you try to drag the 1st item over the 2nd item, you'll see that the 1st item has to be dragged for entire height, like 100% of its height, over the 2nd element, and only then the order of items is swapped.
Am I missing something? Is there any way for me as a programmer to force the plugin to work as I expect it to work? I wish the user to move the 1st item only 50% of its height down, in order for the plugin to detect overlapping and perform reordering.
The short answer is:
There's a bug ticket for this, so it seems like the only option is some form of workaround.
Here's a workaround example that uses a custom sort function, which seemed to answer your question better. I'll keep the below example as well for another approach to the problem.
...
That covers the case with a single direction, but what if you want to implement a grid?
Here's a workaround fiddle that I edited (Grid example w/ insert): fiddle
Note: This doesn't swap blocks, it inserts them and pushes the rest back.
Here's a snip of the javascript / jQuery code involved that mocks 50% coverage:
var height = $(".tab").height();
var height = $(".tab").width();
$('#pointer').sortable({
cursorAt: { top: height/2, left: width/2 },
containment: 'parent',
tolerance: 'pointer'
});
Looking at the widget's code you'll find:
if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
this._rearrange(event, item);
} else {
break;
}
So, due you specifie tolerance: "intersect", this._intersectsWithSides(item) is take it.
And function _intersectsWithSides(item) it's defined here:
_intersectsWithSides: function(item) {
var isOverBottomHalf = this._isOverAxis(this.positionAbs.top +
this.offset.click.top, item.top + (item.height/2), item.height),
isOverRightHalf = this._isOverAxis(this.positionAbs.left +
this.offset.click.left, item.left + (item.width/2), item.width),
verticalDirection = this._getDragVerticalDirection(),
horizontalDirection = this._getDragHorizontalDirection();
it take "item.height/2" and "item.width/2"
You can go with your on function and redefine this behaviour:
_myIntersectsWithSides: function(item) {
var isOverBottomHalf = this._isOverAxis(this.positionAbs.top +
this.offset.click.top, item.top + (item.height/5), item.height),
isOverRightHalf = this._isOverAxis(this.positionAbs.left +
this.offset.click.left, item.left + (item.width/5), item.width),
verticalDirection = this._getDragVerticalDirection(),
horizontalDirection = this._getDragHorizontalDirection();
And that give you 20% (100/5 instead of 100/2) of width and height.
The "50%" it's defined by code.-
Hope this help

FadeIn Div at Mouse Cursor on Keypress [Javascript/JQuery]

I'm trying to make a dynamic javascript menu (contained in a div) appear at a visitor's mouse coordinates when they press ctrl+m on their keyboard (m signifying menu, and ctrl+m not being bound in most browsers as far as I'm aware). This way, wherever they are on my site and wherever their mouse is, they can pull up the menu by just pressing that combination and return to wherever they wish to go. At the same time, having the menu not shown until they press the key allows me to control the design experience completely without having to worry about a nav menu.
I've pulled together two different pieces of code I found on here in an attempt to do this myself, but I'm running into an unexpected issue.
I'm not sure how to denote the ctrl+m key combination in the event handler.
I'm getting a couple of errors on the code checker that I'm not sure how to fix myself.
I'm not sure how to make it so that the menu appears on ctrl+m, and stays there until ctrl+m is pressed again (a toggle switch).
I'm still learning how Javascript works.
Here's the link to the progress I've made so far: http://jsfiddle.net/nrz4Z/
In your example, you're binding the mousemove handler inside the keypress handler. You need to do them separately:
var mouseX;
var mouseY;
$(document).ready(function () {
$(document).mousemove(function (e) {
mouseX = e.pageX;
mouseY = e.pageY;
});
$(document).keypress(function (event) {
if (event.which == 109) {
$('#examples').css({
'top': mouseY,
'left': mouseX
}).fadeIn('slow');
};
});
});
That should allow you to get the position at which to show the menu.
Firstly the use of keypress is not a good idea - web is something that is on an unknowable amount of browsers and devices and plugins and you don't know what shortcuts are bound to especially ones using modifiers with a single key (in this case cmd+m or ctrl+m is an OS shortcut to minimise the window on many OSes. ctrl exists as cmd in os x and not at all on phones.)
To detect multiple key presses check here: Can jQuery .keypress() detect more than one key at the same time?
Next you can detect mouse movements and store them in a variable for use anywhere: How to get mouse position in jQuery without mouse-events?
Your menu should then be at the bottom of the DOM with only body as it's parent:
<nav>
<p>My Menu</p>
<nav>
</body>
Your nav should have whatever styling it needs in the css, as well as:
nav {
position: absolute;
display: none;
/*z-index: 700; nav is at bottom of dom so it will go above anything without a z-index but you may want it to go over other things */
}
When you have detected your key-presses you should do:
$('nav').css({top: mouseYCoord, left: mouseYCoord}).show();
Obviously give your menu a more useful name and don't select upon all 'nav' tags.

Creating an Expanding DIV/Canvas with Horizontal Scrolling with Wheel JavaScript

Ok - here is what I am trying to do. I was looking online for a cool timeline that I can purchase - allowing zoom in zoom out, posting of events on it, and so on. However, all the examples I found are either too expensive or just downright useless.
So, I have decided to create my own, but there are two elements that I am having trouble with.
1) Converting the wheel scroll to left-right scrolling (so not up-down). I can't seem to find an easy and quick way to do this.
But, more importantly..
2) I need the area I will be showing the timeline on to automatically expand as I go about my scrolling. So, if I scroll down, it will add an "equivalent" area on the right, and down, on the left. So I was thinking like making an iFrame (already use these) and when you scroll it just adds more "timeline" on the left or the right, loads what ever it needs to load from the DB/list of events, and so on, ad infinitum, thus creating an ever-expanding list of blocks that are time-sized.
If I can do the two things above, then I am set - the rest (loading/positioning) I can figure out - just these two things are eluding my imagination and ability to find an answer.
Basically you need a horizontal infinite scroll script.
Take this plugin I wrote:
$.fn.hScroll = function( options )
{
function scroll( obj, e )
{
var evt = e.originalEvent;
var direction = evt.detail ? evt.detail * (-120) : evt.wheelDelta;
if( direction > 0)
{
direction = $(obj).scrollLeft() - 120;
}
else
{
direction = $(obj).scrollLeft() + 120;
}
$(obj).scrollLeft( direction );
e.preventDefault();
}
$(this).width( $(this).find('div').width() );
$(this).bind('DOMMouseScroll mousewheel', function( e )
{
scroll( this, e );
});
}
Initialize it with:
$('body').hScroll();
Makes your website a horizontally scrollable website.
Your content div must be wider than your body (ex. 3000px).
As for the infinite scrolling effect you pretty much gotta do that your self because I can't know what kind of data you'll input. But I'll explain.
Your children elements in the content div must be floated to left. (every new appended div will not go to new line).
Set an interval to check if the user's scrollLeft position is near the end of the content (just like pinterest and similar site).
function loadNewData(){ /* Your search for data and update here. */ }
setInterval('loadNewData', 500);
search for new data according to your last one with AJAX. When you get new data, append it into your content div (in a div that's floated left, as I wrote previously), and mark it as your last item.
Maybe you could use your ID to mark the last item on it's div.
<div data-id="467" class="item"> // your data here </div>
You can fetch it with
$('.item:last').attr('data-id');
with jQuery.

change css on scroll event w/ requestAnimation Frame

I want to change the background color of in-viewport elements (using overflow: scroll)
So here was my first attempt:
http://jsfiddle.net/2YeZG/
As you see, there is a brief flicker of the previous color before the new color is painted. Others have had similar problems.
Following the HTML5 rocks instructions, I tried to introduce requestAnimationFrame to fix this problem to no avail:
http://jsfiddle.net/RETbF/
What am I doing wrong here?
Here is a simpler example showing the same problem: http://jsfiddle.net/HJ9ng/
Filed bug with Chromium here: http://code.google.com/p/chromium/issues/detail?id=151880
if it is only the background color, well why don't you just change the parent background color to red and once it scroll just change it to pink?
I change your CSS to that
#dad
{
overflow-y: scroll;
overflow-x: hidden;
width: 100px;
height: 600px;
background-color:red;
}​
I remove some of you Jquery and change it to this
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
});
And I remove this line
iChild.css('backgroundColor', 'red');
But is the Red color it is important that won't work for sure http://jsfiddle.net/2YeZG/5/
I like Manuel's Solution.
But even though I don't get what you're exactly trying to do, I want to point out a few things.
In your fiddle code, I saw that you included Paul Irish's Shim for requestAnimationFrame.
But you never use it.
(It's basically a reliable setTimeOut, nothing else) it's from frame based animations.)
So since you just want to change some CSS properties, I don't see why you would need it. Even if you want transitions, you should rely on CSS transitions.
Other than that your code could look something like
dad.bind('scroll', function() {
dad.css('background-color', 'pink');
eachElemNameHere.css('background-color','randomColor');
});
Also you should ideally not use something like that if you can help it. You should just add and remove class names and add all these properties in your CSS. Makes it work faster.
Also, again I don't quite get it, but you could use the jQuery function to find out each elements' position from the top to have better control.
Your problem seems to be that you only change the background color of the elements which have already been scrolled into view. Your code expects that the browser waits for your code to handle the scroll event before the browser redraws its view. This is most probably not a guarantee given by the HTML spec. That's why it flickers.
What you should do instead is to change the elements which are going to be scrolled into view. This is related to off screen rendering or double buffering as it is called in computer games programming. You build your scene off screen and copy the finished scene to the visible frame buffer.
I modified your first JSFiddle to include a multiplier for the height of the scroll area: http://jsfiddle.net/2YeZG/13/.
dad.bind('scroll', function() {
// new: query multiplier from input field (for demonstration only) and print message
var multiplier = +($("#multiplier")[0].value);
$("#message")[0].innerHTML=(multiplier*100)-100 + "% of screen rendering";
// your original code
var newScrollY = newScrollY = dad.scrollTop();
var isForward = newScrollY > oldScrollY;
var minVal = bSearch(bots, newScrollY, true);
// new: expand covered height by the given multiplier
// multiplier = 1 is similar to your code
// multiplier = 2 would be complete off screen rendering
var newScrollYHt = newScrollY + multiplier * dadHeight;
// your original code (continued)
var maxVal;
for (maxVal = minVal; maxVal < botsLen; maxVal++) {
var nxtTopSide = tops[maxVal];
if (nxtTopSide >= newScrollYHt) {
break;
}
}
maxVal = Math.min(maxVal, botsLen);
$(dadKids.slice(minVal, maxVal)).css('background', 'pink');
});
Your code had a multiplier of 1, meaning that you update the elements which are currently visible (100% of scroll area height). If you set the multiplier to 2, you get complete off screen updates for all your elements. The browser updates enough elements to the new background color so that even a 100% scroll would show updated elements. Since the browser seldom scrolls 100% of the area in one step (depends of the operating system and the scroll method!), it may be sufficient to reduce the multiplier to e.g. 1.5 (meaning 50% off screen rendering). On my machine (Google Chrome, Mac OS X with touch pad) I cannot produce any flicker if the multiplier is 1.7 or above.
BTW: If you do something more complicated than just changing the background color, you should not do it again and again. Instead you should check whether the element has already been updated and perform the change only afterwards.

Categories