custom js image viewer is loading slower after each "next" key press - javascript

I've built a custom image viewer that works fine, but each time I use the arrows to view the next or previous image, it loads slower and slower. By the 10th image, it could take many minutes, or even freeze. The snippet I use to open the viewer is the same as the one I use to move to the next image, and each open is always lightning fast; only when I use the arrow keys does it get slower. Sometimes the .php file won't load at all and it'll just say "undefined", which is coming from the JS somewhere, I believe?
function image_load(id) {
$('.view').empty().load(image-viewer.php?id='+id, function() {
$(document).keyup(function(e) {
if (e.keyCode == 39) {
var next = $('#next').attr('alt');
if(next != "null") {
image_load(next);
return false;
}
}
if (e.keyCode == 37) {
var prev = $('#prev').attr('alt');
if(prev != "null") {
image_load(prev);
return false;
}
}
});
});
}
So the next/previous reference the function within which their contained. Is it creating an endless loop somehow and slowing down the processor?

As per my comment, you are creating an endless loop because you are repeatedly binding the key events over and over again. What you should do is separate the function declaration away from event handlers:
var image_load = function(id) {
$('.view').empty().load('image-viewer.php?id='+id);
};
$(document).keyup(function(e) {
// Prevent default key actions
e.preventDefault();
// Evaluate pressed keys
if (e.keyCode == 39) {
var next = $('#next').attr('alt');
if (next) image_load(next);
} else if (e.keyCode == 37) {
var prev = $('#prev').attr('alt');
if (prev) image_load(prev);
}
});

Related

How to get user keyboard input asynchronously in C# / asp.Net / Razor

I work on a simple game clone of pacman. The only thing i have a problem with is how to get input from the user via keyboard to change the direction of the pacman (left, right, up, down).
Currently, i am using html buttons to redirect the window to the action which changes the variable in a "core" class. It works but not at all times. Pacman moves via javascript timeout function, where each 250 miliseconds, pacman moves in a direction which is stored in mentioned variable. It has sometimes a problem to capture the button click. (i guess because of the js timeout) Any help appriciated!
Mentioned JS code:
<script type="text/javascript">
setTimeout(function () {
window.location.href = '/Home/Move';
}, 250);
</script>
Try this :
document.onkeydown = function(e) {
if (e.keyCode == '38') {
// up arrow
}
else if (e.keyCode == '40') {
// down arrow
}
else if (e.keyCode == '37') {
// left arrow
}
else if (e.keyCode == '39') {
// right arrow
}
}

on trigger click event script called 2 time in first attempt

I am creating an image gallary using owl carousel and php.there mouse click event working perfectly but when click command over keyboard having problem skip one image on prev keyup only and only first time. which code are calling after keyup function when write that code inside that function working perfectly
$(document.documentElement).keyup(function(event) {
// handle cursor keys
if (event.keyCode == 37) {
$(".prev").click();
});
var prevkey = $(".prev");
prevkey.unbind("click").click(function() {
$(".reset").click();
setTimeout(function() {
$(".printable").load(function(){
$(".owl-carousel").myfunction();
});
}, 200);
curEle = $(".item.active").parent();
//console.log(curEle);
if(curEle.find(".item").attr("data-id")==0)
{
$(this).addClass("disabled");
}
else
{
$(this).removeClass("disabled");
prevEle = curEle.prev();
console.log(prevEle);
prevEle.find(".item").addClass("active");
curEle.find(".item").removeClass("active");
prevEle.find(".printable").attr("src",prevEle.find(".printable").attr("data-src"));
carousel.trigger("owl.prev");
curEle.find(".printable").attr("src","");
}
});
Insert preventDefault() to avoid other events than yours...
$(document.documentElement).keyup(function(event) {
// handle cursor keys
event.preventDefault();
if (event.keyCode == 37) {
$(".prev").click();
}
});
EDIT check this answer if you're using IE8
try this using one will prevent a second call
$(".prev").one("click",function(){
//your stuff
});

Fire function only once if another has already been fired

I have created two functions. To keep it simple lets take for an example the following:
I got functions firing different events for the same objects. You can activate them using your keyboard arrows
$("body").keydown(function(e) {
if (event.which == 39) open_second_layer();
});
$("body").keydown(function(e) {
if (event.which == 37) open_first_layer();
});
As soon as I have fired one function and press the same key again it fires the animation one more time (unnecessarily).
Because of that as soon as the function open_second_layer has been fired, it should not be able to be fired again, until open_first_layer is fired again. The same should be the case the other way round.
I found .bind and .when as possible solutions, but can't figure out how to use them the right way for that case. I appreciate every suggestions or keywords to google.
You can keep a state variable and track when changes are made to it:
var state_changed = (function() {
var current = null;
return function(state) {
if (state == current) {
return false;
}
current = state;
return true;
};
}());
function open_first_layer()
{
if (!state_changed(1)) {
return;
}
// rest of code
}
function open_second_layer()
{
if (!state_changed(2)) {
return;
}
// rest of code
}
$("body").keydown(function(e) {
if (event.which == 39) {
open_second_layer();
} else if (event.which == 37) {
open_first_layer();
}
});
You can use jQuery's one().
In your first click handler, you bind the second one.
In your second click handler, you bind the first one.
sample
<div id=activate-first>first</div>
<div id=activate-second style="display:none;">second</div>
$(document).ready(function () {
function slide_first(){
$('#activate-first').show();
$('#activate-second').hide();
$('#activate-second').one('click', slide_first);
};
function slide_second(){
$('#activate-first').hide();
$('#activate-second').show();
$('#activate-first').one('click', slide_second);
};
$('#activate-first').one('click', slide_second);
$('#activate-second').one('click', slide_first);
});
Put the other function inside slide_first, like:
function slide_first(){
// other code
$('#activate_second').one('click', slide_second);
}
$('#activate_first').one('click', slide_first);
or use an Anonymous function to do the same:
$('#activate_first').one('click', function(){
// slide_first code here
$('#activate_second').one('click', function(){
// slide_second code here
});
});
Maybe your really want:
function recursiveSlider(){
$('#activate_first').one('click', function(){
// slide_first code here
$('#activate_second').one('click', function(){
// slide_second code here
recursiveSlider();
});
});
}
recursiveSlider();
This is a perfect use case for delegation. You have a single click event, and whenever the event happens, you determine what has been clicked, and you take action accordingly:
$(document.body).on("click", function(ev) {
var $targ = $(ev.target);
if ($targ.is('#button_1')) {
// someone clicked #button_1
}
if ($targ.is('.page-2 *')) {
// something inside of .page-2 was clicked!!
}
});
UPDATE: now the OP has included more code, I'm not sure the issue is - there's no need to bind and unbind events...
http://jsfiddle.net/ryanwheale/uh63rzbp/1/
function open_first_layer() {
$('#first_panel').addClass('active');
$('#second_panel').removeClass('active');
}
function open_second_layer() {
$('#first_panel').removeClass('active');
$('#second_panel').addClass('active');
}
// one event === good
$("body").keydown(function(e) {
if (event.which == 39) open_second_layer();
if (event.which == 37) open_first_layer();
});
... or if you're trying to build a slider, I suggest changing your naming convention:
http://jsfiddle.net/ryanwheale/uh63rzbp/2/
var current_layer = 1,
$all_layers = $('[id^="panel_"]'),
total_layers = $all_layers.length;
function move_layer (dir) {
current_layer += dir;
if (current_layer < 1) current_layer = total_layers;
else if (current_layer > total_layers) current_layer = 1;
$all_layers.removeClass('active');
$('#panel_' + current_layer).addClass('active');
}
// one event === good
$("body").keydown(function(e) {
if (event.which == 39) move_layer(1);
if (event.which == 37) move_layer(-1);
});
move_layer(0);

How can you define something to happen and remain in that state?

I have a game in jquery in which if you press right key on the keyboard it loads a certain image and if you press left key on the keyboard it loads another image . My problem is that all of this is happening in an interval that keeps repeating . As soon as the program finds that my right key is no longer pressed it will automatically draw the second Image. I want it to do the following :
- if I press right arrow, it will draw the Image1 and remain in that state until I press the left key
-if I press left arrow, I want my Image2 to be drawn and remain in that state until I press the right key
If I do this in a while loop my web page will crash because it will stay in that while loop and what follows won t be executed .
This is working, but as soon as I release the right key, rightDown will be false and when the program finds the if statement again it will draw my Image2 . (the interval is really fast)
if(rightDown)drawImage1();
else drawImage2();
If I use this
if(rightDown)drawImage1();
else if(leftDown) drawImage2();
and I don t press the left or right key no image will be drawn.
rightDown and leftDown
function onKeyDown(evt) {
if (evt.keyCode == 39) rightDown = true;
else if (evt.keyCode == 37) leftDown = true;
else if (evt.keyCode == 38) upKeyDown = true;
else if(evt.keyCode == 40) downKeyDown = true;
}
and the part when they are not clicked
function onKeyUp(evt) {
if (evt.keyCode == 39) rightDown = false;
else if (evt.keyCode == 37) leftDown = false;
else if (evt.keyCode == 38) upKeyDown = false;
else if (evt.keyCode == 40) downKeyDown = false;
}
$(document).keydown(onKeyDown);
$(document).keyup(onKeyUp);
Let's say you have a function to draw your default image, named drawDefault(); using this code:
window.onload = drawDefault;
Such that, upon the window's loading, it will draw the default picture (can also be used as window.onload = drawImage[1,2](); (where [...] denotes choice).
If you have already defined a .onload method for window, then you can simply extend your .onload function:
window.onload = function(){
// ... code ...
drawDefault();
}
Or, with a more interesting way:
if(!window.onload){
window.onload = drawDefault;
} else {
var on = window.onload;
window.onload = function(){
on();
drawDefault();
}
}
Combined with this, use your code:
if(rightDown)drawImage1();
else if(leftDown) drawImage2();
(Personally, I'd used {...} to enclose if, else if, and else statements, as it's easier to read (and how hard is it to press two extra keys or such?).
The outcome will be, if I have interpreted both your question and your code (what there was of it, anyhow) correctly, what will happen is that:
The default image will be displayed
On rightDown, the right image will be displayed, and,
On leftDown, the left image will be displayed.
Hope it helps!!

Key Navigation with Javascript

Please Help! I have spent a week to complete this game and this is the final huddle i have been stuck with for a couple of days now. I know some techy out there would probably take a glance and flick something in place. But I'm not very sophisticated with javascript and therefore need some help.
$(document).keydown(function(e){
// left arrow
if (e.keyCode == 37 && currentCell > 0) {
currentCell--;
ChangeCurrentCell();
return false;
}
// up arrow
if (e.keyCode == 38 && currentRow > 0) {
currentRow--;
ChangeCurrentCell();
return false;
}
// right arrow
if (e.keyCode == 39 && currentCell < MAX_CELL) {
currentCell++;
ChangeCurrentCell();
return false;
}
//down arrow
if (e.keyCode == 40 && currentRow < MAX_ROW) {
currentRow++;
ChangeCurrentCell();
return false;
}
// enter key
if (e.keyCode == 13) {
}
});
function ChangeCurrentCell()
{
document.getElementById(Boxes[currentRow + currentCell]).focus();
SimulateMouseOver(document.getElementById(Boxes[currentRow + currentCell]));
}
// function will trigger event of selecting current focus.
function selectElement()
{
}
$(document).ready(function(){
loadDivs()
// will give initial focus to top left element paving way for key navigation
ChangeCurrentCell();
// above gives first element in Boxes the focus when loading.
The div element will not focus despite getting it and calling the focus method, i have tried to trigger mousehover on the element with no luck. Please assist me, i put my masters thesis aside despite already being on a tight schedule to do this game which is a requirement for a job position. I have done whole the whole game logic and it all works well, if i send the code in as it is it will definitely be discarded because it doesnt meet the key navigation requirement ... i am desperate i will even pay if i need to -frustrated Student
Look at this
It's my solution for a test, maybe the same...maybe can help you :) If it is, please use it as a hint and don't copy all my code :D
Regards,
L.
You can bind to the document.keydown event to capture key strokes. Then you can use event.which (normalized by jQuery) to determine which key was pressed.
$(document).on("keydown", function (event) {
if (event.which === 37) {
//code for left arrow
} else if (event.which === 38) {
//code for up arrow
} else if (event.which === 39) {
//code for right arrow
} else if (event.which === 40) {
//code for down arrow
}
});
UPDATE
I just noticed you didn't tag your question with jQuery. To use native JS you'll have to change how you bind to the document.keydown event and how you determine the key that was pressed (different browser implementations store the info under different indexes of the event object).
to make it more convenient () not necessary:
`var LEFT = 37, UP = 38, RIGHT = 39, DOWN = 40, SPACE = 32;`
then bind to keydown, keypress doesn't catch arrow keys
and do something like this:
$(document).bind("keydown", function (e){
var which = e.which;
var navigationKeyWasPressed = which !== undefined && which >= 39 && which <= 40;
//do nothing if no significant key was pressed
if (!navigationKeyWasPressed ) {
return;
}
if ($(".selectedWithKey").length === 1){
switch (which) {
case LEFT:
//...
break;
case UP:
//...
break;
case RIGHT:
//...
break;
case DOWN:
//...
break;
case SPACE:
//turn card
break;
default: //non arrow pressed
//...
}
} else {
// if no card is selected, select one to start arrow navigation
$(".sponsor:first").addClass("selectedWithKey")
}
});

Categories