I'm building a script that will, from a gallery, scroll and center an image after a mouse/keyboard event.
Once an image is "cliked", only the clicked image will be displayed and center on the screen, all others will be hidden.
Then, the user is able to click again in order to scroll to the next img.
Note: when the last img is fired, we will display the bottom of the page.
Report:
If we are only using the mouse, the script is working as I want.
If we are only using the bottom key, the script is working as I want.
If we are using the keyboard (many times) and after the mouse,
functions will be lauch many times. I think this is due to the .on
method (keydown click)
Does any one know how to handle this events to make them work together?
Here is an Jsfidle/example of it
HTML
<div id="galleries" class="">
<div id="pictures-content" class="1">
<img src="http://www.clipartbest.com/cliparts/RiA/jnd/RiAjnd9iL.png">
</div>
<div id="pictures-content" class="2">
<img src="http://www.clker.com/cliparts/v/N/K/k/N/3/number-2-design-md.png">
</div>
<div id="pictures-content" class="3">
<img src="http://www.clker.com/cliparts/x/B/x/Y/R/L/number-3-md.png">
</div>
<div id="pictures-content" class="4">
<img src="http://www.clker.com/cliparts/K/w/R/r/V/Z/number-4-md.png">
</div>
<div id="pictures-content" class="5">
<img src="http://www.bubblews.com/assets/images/news/23937009_1390558154.png">
</div>
<div id="pictures-content" class="6">
<img src="http://www.olneymiddle.milton-keynes.sch.uk/Year6/wp-content/uploads/2014/02/number-6-md-Copy.png">
</div>
<div id="pictures-content" class="7">
<img src="http://www.clker.com/cliparts/V/K/h/8/c/A/number-7-md.png">
</div>
<div id="pictures-content" class="8">
<img src="http://www.clker.com/cliparts/M/L/0/g/q/R/red-rounded-with-number-8-md.png">
</div>
<div id="pictures-content" class="9">
<img src="http://www.clker.com/cliparts/h/S/2/m/C/o/red-rounded-with-number-9-md.png">
</div>
</div><!-- galleries --!>
jQuery
presentation_mode_stop_scrolling = "off";
// Calling functions
$(document).ready(function(){
// Init the dom - add a class number to each img
init_dom_class();
var picture_to_center = "";
var key_press = "";
var counter =0;
var max = $("#galleries #pictures-content").length;
$("#galleries #pictures-content").off('click');
$("#galleries #pictures-content").on('click',undisplay_center_pictures);
//quit presentation mode + display all content + init variables on scroll event
$(window).scroll(function () {
if ((presentation_mode_stop_scrolling === "off")) {
$("#galleries #pictures-content").on('click');
var i=1;
// We are checking if we use to be in the presentation mode to removed it just once
// Also we display all the pictures again
var class_gall= $("#galleries").attr('class');
// display all content + init variables
if(class_gall=="picture_presentation") {
$("#galleries #pictures-content").each(function() {
$("#galleries ."+i+" img").animate({opacity:1});
i++;
});
$("#galleries").removeClass('picture_presentation');
$("#header").animate({opacity:1});
$("#description").animate({opacity:1});
$("#bottom_site").animate({opacity:1});
key_press == "";
}
}
});
//quit presentation mode + display all content + init variables on resize event
$(window).resize(function () {
if (presentation_mode_stop_scrolling === "off"){
//quit presentation mode
var i=1;
// We are checking if we use to be in the presentation mode to removed it just once
// Also we display all the pictures again
var class_gall= $("#galleries").attr('class');
if(class_gall=="picture_presentation"){
// console.log("QUITTING");
// console.log("class_gall: "+class_gall);
$("#galleries #pictures-content").each(function() {
$("#galleries ."+i+" img").animate({opacity:1});
i++;
});
$("#galleries").removeClass('picture_presentation');
$("#header").animate({opacity:1});
$("#description").animate({opacity:1});
$("#bottom_site").animate({opacity:1});
key_press == "";
}
}
});
$(document).keydown(function(eventkeyboard) {
eventkeyboard.preventDefault();
//eventkeyboard.which is set by jQuery for those browsers that do not normally support eventkeyboard.keyCode.
// WE HAVE TO RESET THIS VALUE OTHERWISE THE ANIMATION IS BROKEN
key_press = "";
var keyCode = eventkeyboard.keyCode || eventkeyboard.which;
// KEY UP
if (keyCode === 38) {
return false;
}
// KEY DOWN
if (keyCode === 40) {
// console.log("key down");
// Unbind the click eventkeyboard with the presentation_mode_stop_scrolling variable
// console.log("presentation_mode_stop_scrolling: "+presentation_mode_stop_scrolling);
// allow keyboard action when the scrolling animation is completed
if (presentation_mode_stop_scrolling === "off"){
// IF EACH OF THE IMAGES ARE VISIBLE WE START FROM THE BOTTOM
var class_galleries= $("#galleries").attr('class');
if(class_galleries=="picture_presentation"){
// console.log("key down - THERE IS AN ACTIVE IMAGE"); // ACTIVE IMG
// THERE IS AN ACTIVE IMAGE
key_press = "down_with_a_focus_image"; // define the key pressed
var picture_to_center = retrieve_the_selected_img(eventkeyboard,key_press); // get img to center
// console.log("picture_to_center: "+picture_to_center);
hide_all_website_items_except_img_to_center(picture_to_center); // hide all img except the img to center
scroll_to_the_new_picture_to_center(picture_to_center);
return false;
} else {
// console.log("key down - THERE ISN'T ANY ACTIVE IMAGE"); // NO ACTIVE IMG
key_press = "down_without_any_focused_image"; // define the key pressed
var picture_to_center = retrieve_the_selected_img(eventkeyboard,key_press); // get img to center
$('#galleries #pictures-content').css({'background-image' : 'none'}); // Removing the background loading img
$("#galleries").addClass('picture_presentation'); // Add the presentation
hide_all_website_items_except_img_to_center(picture_to_center); // hide all img except the img to center
scroll_to_the_new_picture_to_center(picture_to_center);
return false;
}
}
return false;
}
// KEY LEFT
if (keyCode === 37) {
return false;
}
// KEY RIGHT
if (keyCode === 39) {
return false;
}
});
// We are calling this function on click event
function undisplay_center_pictures(event) {
event.preventDefault();
$("#galleries #pictures-content").off('click');
var class_galleries = $("#galleries").attr('class'); // we check if an image is already center
// console.log("class_galleries: "+class_galleries);
var picture_to_center = retrieve_the_selected_img(event); // populate the picture_to_center with the selected img
// console.log("picture_to_center: "+picture_to_center);
// Manage the picture_presentation mode and return the next image to center
if ($("#galleries").attr('class') === "picture_presentation") {
// no key for the moment
var new_picture_to_center = show_and_get_new_picture_to_center_and_hide_previous(event,picture_to_center,max);
// console.log("new_picture_to_center: "+new_picture_to_center);
// var picture_to_center = show_and_get_new_picture_to_center_and_hide_previous(picture_to_center,max);
scroll_to_the_new_picture_to_center(new_picture_to_center);
} else {
// hide everything except the img with the picture_to_center class
hide_all_website_items_except_img_to_center(picture_to_center);
scroll_to_the_new_picture_to_center(picture_to_center);
// ADD THE PICTURE PRESENTATION CLASS TO ENTER TO THE PRESENTATION MODE
$("#galleries").addClass('picture_presentation');
}
};
// Init the dom - add a class number to each img
function init_dom_class() {
var i=1;
$("#galleries #pictures-content").each(function() {
$(this).addClass(""+i+"");
i++;
});
};
// return the selected img
function retrieve_the_selected_img (event,key_press){
event.preventDefault();
// We are using only the mouse for the moment so
// console.log("key_press: "+key_press);
if (key_press == "down_without_any_focused_image") {
// var picture_to_center = 1;
return 1;
}
else if (key_press == "down_with_a_focus_image") {
$("#galleries #pictures-content img").each(function() {
var all_class_galleries = $(this).css("opacity");
if (all_class_galleries==1){
picture_to_center = parseInt($(this).parent().attr('class'));
// DO SOMETHING ON IMG TO CENTER
picture_to_center = picture_to_center+1;
}
});
return picture_to_center;
}
else {
// mouse click event
return parseInt($(event.target).parent().attr('class'));
}
};
// hide everything except the img with the picture_to_center class
function hide_all_website_items_except_img_to_center(picture_to_center){
// console.log(picture_to_center);
console.log("hide_all_website_items_except_img_to_center");
// Make a condition redirect user to bottom of the page on last image and display all content
if(picture_to_center > parseInt($("#galleries #pictures-content").length)) {
// FADE IN ALL PICTURES
z=1;
$("#galleries #pictures-content").each(function() {
$("#galleries ."+z+" img").animate({opacity:1});
z++;
});
$("#header").animate({opacity:1});
$("#description").animate({opacity:1});
$("#bottom_site").animate({opacity:1});
// REMOVE THE presentation mode
$("#galleries").removeClass('picture_presentation');
$("body").scrollTo($(document).height(), 800, {
onAfter: function(){
setTimeout(function(){
presentation_mode_stop_scrolling = "off";
// console.log("presentation_mode_stop_scrolling: "+presentation_mode_stop_scrolling);
$("#galleries #pictures-content").on('click',undisplay_center_pictures);
},100);
}
});
} else {
$("#galleries #pictures-content").each(function() {
var all_class_galleries = parseInt($(this).attr('class'));
if(all_class_galleries!=picture_to_center) {
$("#galleries ."+all_class_galleries+" img").animate({opacity:0});
} else{
// $("#galleries ."+all_class_galleries+" img");
// With keyboard, we need to display the next img
$("#galleries ."+all_class_galleries+" img").animate({opacity:1});
}
});
$("#header").animate({opacity:0});
$("#description").animate({opacity:0});
$("#bottom_site").animate({opacity:0});
}
return true;
};
// Hide the previous current img + Update the picture to center variable with the new img value + return new picture to center
function show_and_get_new_picture_to_center_and_hide_previous(event,picture_to_center,max){
event.preventDefault();
console.log("show_and_get_new_picture_to_center_and_hide_previous");
// We hide the previous centered img + get new picture to center id
if (picture_to_center < max) {
$("#galleries ."+picture_to_center+" img").animate({opacity:0});
picture_to_center++;
}
else if (picture_to_center == max){
// We go to the bottom of the page
picture_to_center++; // we increment picture_to_center to go to the bottom of the page
// console.log("We have to scroll to the bottom");
// last_picture = 1;
}
// console.log("new picture to center: "+picture_to_center);
// FADE IN THE NEXT IMAGE
$("#galleries ."+picture_to_center+" img").animate({opacity:1});
return picture_to_center;
};
// last picture for keyboard
function scroll_to_the_new_picture_to_center(picture_to_center){
// Stop the user to be able to canceled the presentation mode by scrolling or resizing the window
// during the scrolling event
// Not working properly -> need to check
// console.log(picture_to_center);
console.log("scroll_to_the_new_picture_to_center");
console.log("counter: "+counter);
counter++;
presentation_mode_stop_scrolling = "on";
// Calculate the top margin to center the image inside the screen
var window_height = $(window).height();
var img_height = $("#galleries ."+picture_to_center+" img").height();
var offset = (window_height-img_height)/2;
var max = parseInt($("#galleries #pictures-content").length);
// console.log("max: "+max);
// We are scrolling to the bottom of the page
if(picture_to_center > max){
// FADE IN ALL PICTURES
// picture_to_center = 0;
z=1;
$("#galleries #pictures-content").each(function() {
$("#galleries ."+z+" img").animate({opacity:1});
z++;
});
$("#header").animate({opacity:1});
$("#description").animate({opacity:1});
$("#bottom_site").animate({opacity:1});
console.log("picture_presentation should be removed");
$("#galleries").removeClass('picture_presentation');
console.log("picture_presentation should be removed");
$("body").scrollTo($(document).height(), 800, {
onAfter: function(){
setTimeout(function(){
presentation_mode_stop_scrolling = "off";
// console.log("presentation_mode_stop_scrolling: "+presentation_mode_stop_scrolling);
$("#galleries #pictures-content").on('click',undisplay_center_pictures);
},100);
}
});
}
else{
$("body").scrollTo($('.'+picture_to_center), 800, {
offset:-offset,
onAfter: function () {
setTimeout(function(){
presentation_mode_stop_scrolling = "off";
// console.log("presentation_mode_stop_scrolling: "+presentation_mode_stop_scrolling);
// $("#galleries #pictures-content").on('click'); -> not working, we need to specify the function
$("#galleries #pictures-content").on('click',undisplay_center_pictures);
},100);
}
});
}
return true;
};
});
As the .on method was used to cath the "keydown" and the "click" event, I had to unbind the "click" event on the "keydown" event.
$(document).keydown(function(eventkeyboard) {
eventkeyboard.preventDefault();
$('#galleries #pictures-content').off('click');
... etc
Related
I am new to web development and I love it.
But I've have encountered a problem and I can't figure it out.
When i lose my focus on my browser tab, my fade effect ,made for my images when they are change, is turns on multiple times. .
Another problem, i really want my images inside of my div element to be like : http://jsfiddle.net/eb51hxj1/ when i resize the browser.
<div class="divImage">
<img id="image"> </div>
<div>
My code is :
https://jsfiddle.net/a2bsarfb/
Make a new var that checks for the window focus. When the window focus is gone then just skip the rest of the code.
At the very top add a new var:
var lostFocus = false;
In the Caller function add:
if(lostFocus){ return false; }
So it will look like:
function Caller() {
var imag = ["https://i.ytimg.com/vi/tq0H6nQMdNk/maxresdefault.jpg", "https://i.ytimg.com/vi/4qVMnkF7W60/maxresdefault.jpg", "https://s-media-cache-ak0.pinimg.com/originals/52/1d/e6/521de6a52e774664745132156448f43b.jpg"];
var numarImagini = imag.length - 1;
var i = Math.floor((Math.random() * imag.length));
Rotate(imag[i], i);
i++;
setInterval(function() {
if(lostFocus){ return false; }
if (i > imag.length - 1) {
i = 0;
Rotate(imag[i], i);
i++;
} else {
Rotate(imag[i], i);
i++;
}
}, 2000)
}
And at the bottom add the event listeners:
window.onblur = function() { lostFocus = true; };
window.onfocus = function() { lostFocus = false; };
I am building a news feed with slides that show a summary and a read more button that when clicked reveals the rest of the content.
Here is a jsFiddle: http://jsfiddle.net/pbunz5ue/1/
When Read More is clicked the story opens and the scrolling stops, then the user clicks Less, its hides the story and continues scrolling.
When Read More is clicked I need the scroll of the div to be aligned so that the opened story starts at the top of the div. My slider does this perfectly the first round the stories make, once they are displayed a second time from the button up this no longer works.
Can someone explain why ??
Here is my code:
JS:
$(document).ready(function() {
//User clicks Read More, add 'open' class to news item
$('.news-read-more').on('click', function() {
blockedSlider = true;
clearInterval(myTimer);
$('.news-list').children('li').each(function() {
$(this).removeClass('open');
});
$(this).parent().toggleClass('open');
var n = $(this).parent();
var pos = n.position();
$('.news-slider-wrapper').scrollTop(pos.top);
});
//User clicks Less, remove 'open' class from news item
$('.news-read-less').on('click', function() {
if (blockedSlider == true) {
blockedSlider = false;
$(this).parent().removeClass('open');
myTimer = setInterval(slideLoop, 2000)
}
});
var myTimer = setInterval(slideLoop, 2000)
var blockedSlider = false;
function slideLoop() {
// Work out width of current slider size
var widthPx = $('.news-list-item').css('height');
var width = widthPx.substring(0, widthPx.length - 2);
// Work out current left
var left = $('.news-list').css('top');
left = left.substring(0, left.length - 2);
if (left <= -(width * 2)) {
var neg = '-' + widthPx;
$('.news-list').css('top', neg);
var slide = $('.news-list li:first');
$('.news-list').children('li:first').remove();
$('.news-list ').append(slide);
//User clicks Read More, add 'open' class to news item
$('.news-read-more').on('click', function() {
blockedSlider = true;
clearInterval(myTimer);
$('.news-list').children('li').each(function() {
$(this).removeClass('open');
});
$(this).parent().toggleClass('open');
var n = $(this).parent();
var pos = n.position();
$('.news-slider-wrapper').scrollTop(pos.top - 360);
});
//User clicks Less, remove 'open' class from news item
$('.news-read-less').on('click', function() {
if (blockedSlider == true) {
blockedSlider = false;
$(this).parent().removeClass('open');
myTimer = setInterval(slideLoop, 2000)
}
});
var move = "-=" + widthPx;
$('.news-list').animate({ top: move }, "slow", "swing");
}
else {
var move = "-=" + widthPx;
$('.news-list').animate({ top: move }, "slow", "swing");
}
}
});
The problem is caused by negative "top" position of .news-list that busts the position of the opened element.
-> I update your fiddle: http://jsfiddle.net/pbunz5ue/3/ <-
What I've changed
the main error:
when you calculate the position you've not considered the negative top offset of the news container .news-list when it slide up:
I've changed this two lines:
var pos = n.position();
$('.news-slider-wrapper').scrollTop(pos.top);
in:
var pos = n.position().top + parseInt($(".news-list").css("top")) || n.position().top;
$('.news-slider-wrapper').scrollTop(pos);
If $(".news-list") has top position I add It to the calculation of position (if the result is auto there is a fallback that prevent NaN result || n.position().top)
You had duplicated the handler $('.news-read-more').on('click') and $('.news-read-less').on('click'); I deleted those within the function because they seems useless.
EDIT:: .on click issue
Try this two way to solve your problem:
1.
If you have some problem when new item was added into your list try to bind the event to the "items" container .news-list and filter the selector every time it will fire:
$('.news-read-more').on('click', function() { //...
$('.news-read-less').on('click', function() { //...
becomes:
$('.news-list').on('click','.news-read-more', function() { //...
$('.news-list').on('click','.news-read-less', function() { //...
the container .news-list never change during your animation, and DOM manipulation.
2.
An other way is to change this rows, in your code:
var slide = $('.news-list li:first');
$('.news-list').children('li:first').remove();
$('.news-list ').append(slide);
becomes:
var slide = $('.news-list li:first');
$('.news-list ').append(slide);
or:
$('.news-list ').append('.news-list li:first');
if you .remove the element, (I think) you unbind all event because you remove the element from DOM, but you not need to remove you need to move it from top to bottom. This way prevent the unbind of click event.
I hope to had understand the problem :).
sorry for may bad english
Based on this script I found on Stack Overflow, I tried adapting it to fade out an editor panel on a HTML page. Fading out works fine, but I'd like limit the fade-out from being triggered.
What I hope to accomplish is to prevent the fade-out whenever the mouse is over the editor panel (and child controls) or when there's keyboard activity in one of the input children.
var i = null;
// this part is working
$("#my-canvas").mousemove(function() {
clearTimeout(i);
$("#panel,#btn-panel-toggle,#fps").fadeIn(200);
var i = setTimeout('$("#panel,#btn-panel-toggle,#fps").fadeOut(800);', 3000);
})
// this part is not working
$("#panel").mouseover(function() {
clearTimeout(i);
})
For a live example, please check out this jsFiddle.
Two independent variables are needed here to indicate, whether the input#sc-url is focused and div#panel is hovered by mouse or not. Then you can handle the timer with these functions:
$(function () {
var t = null; //timer
var is_url_focused = false, is_panel_hovered = false;
var panel = $('#panel');
function hide_panel(){
if (t) {
clearTimeout(t);
}
t = setTimeout(function(){
if (is_url_focused || is_panel_hovered) {
return;
}
panel.stop().animate({
opacity:0
},800, function(){
panel.hide(); // == diplay:none
});
},2000);
}
function show_panel(){
panel.show().stop().animate({
opacity:1
},800);
}
$('#my-canvas').mouseenter(function(){
show_panel();
}).mouseleave(function(){
hide_panel();
});
$('#panel').hover(function(){
is_panel_hovered = true;
show_panel();
}, function(){
is_panel_hovered = false;
hide_panel();
});
$('#sc-url').focus(function(){
is_url_focused = true;
show_panel();
}).blur(function(){
is_url_focused = false;
hide_panel();
});
$('#btn-panel-toggle').click(function(){
if (panel.is(':hidden')) {
panel.css('opacity',1).show();
} else {
panel.css('opacity',0).hide();
}
});
});
http://jsfiddle.net/w9dv4/3/
Creating an accordion - on the slide - the elements underneath the element that is sliding seem to move down a px and then back up, creating a juddering effect.
$(document).ready(function() {
//Promos banners rotation and accordion
$(function(){
var $accordionList = $('.accordion').find('li');
var numberOfItems = $accordionList.length;
var currentItem = 0;
// Set first item to active
$accordionList.eq(currentItem).addClass('active').find('.content').slideToggle(800, function() {});
// Loops through promos
var infiniateLoop = setInterval(function() {
if(currentItem == numberOfItems - 1){
currentItem = 0;
}
else {
currentItem++;
}
// Remove active class, if is has it, and close content
$accordionList.parent().find('li.active').removeClass('active')
.find('.content').slideToggle(800, function() {
});
// Add active class and open content
$accordionList.eq(currentItem).addClass('active').find('.content').slideToggle(800, function() {
});
}, 4000 );
// Click to show promo
$accordionList.on('click', function () {
// Stop rotation
clearInterval(infiniateLoop);
var $accordionHead = $(this);
// Remove active class, if is has it, and close content
if($accordionHead.hasClass('active')) {
// Do nothing
}
else {
$accordionHead.parent().find('li.active').removeClass('active')
.find('.content').slideToggle(800, function() {
});
// Add active class and open content
$accordionHead.addClass('active').find('.content').slideToggle(800, function() {
});
};
});
});
});
Fiddle here demonstrating the problem
I've seen some suggestions that you fix the height of the content div - but the site is responsive so that won't work.
Ya, I've had this problem before to. My favorite fix is to just make my own .slideToggle()
div = $('div');
height = div.height();
width = div.width();
$('div').click( function() {
if ($(this).hasClass('hidden')) {
$(this).animate({height: "0", width: "0"}, 200).hide().addClass('hidden');
} else {
$(this).animate({height: height, width: width}, 200).show().removeClass('hidden');
}
});
You could even wrap it in a prototype function if you wanted to.
I'm trying to create a tab menu. And I need this coded in regular javascript, not jquery.
$(document).ready(function() {
//When page loads...
$(".general_info_content").hide(); //Hide all content
$("ul.general_info_tabs li:first").addClass("active").show(); //Activate first tab
$(".general_info_content:first").show(); //Show first tab content
//On Click Event
$("ul.general_info_tabs li").click(function() {
$("ul.general_info_tabs li").removeClass("active"); //Remove any "active" class
$(this).addClass("active"); //Add "active" class to selected tab
$(".general_info_content").hide(); //Hide all tab content
var activeTab = $(this).find("a").attr("href"); //Find the href attribute value to identify the active tab + content
$(activeTab).fadeIn(); //Fade in the active ID content
return false;
});
});
The core of what you want to do is below - I'm sure there are a thousand different ways to do each task:
Remove a CSS class from an element:
var classes = document.getElementById([id]).className.split(" ");
for(var i = 0; i < classes.length; i++)
if(classes[i] == removeClass)
classes[i] = "";
document.getElementById([id]).className = classes.join(" ");
Add a CSS class to an element:
document.getElementById([i]).className += " " + addClassName;
Hide an element:
document.getElementById([i]).style.display = "none";
Fade an element:
// not tested, but based on tested/used code
function fade(el, opacity, fadeInTime) {
if (opacity < 100) {
el.style.opacity = opacity / 100;
el.style.filter = "alpha(opacity=" + opacity + ")";
opacity += 5;
setTimeout(function () { fade(el, opacity, fadeInTime); }, fadeInTime / 5);
}
}
To find all elements by CSS and tag name:
var matches = new Array();
var all = document.getElementByTagName(searchTagName);
for(var i = 0; i < all.length; i++){
if(all[i].className.replace(searchClassName, "") != all[i].className) {
matches.push(all[i].className);
}
}
// do something with (i.e., return or process) matches
And for the record, I find it encouraging, not unreasonable, that a person using the jQuery library wants to know how to do get things done with native JS/DOM.
More functions to complement Brian's post. Good luck.
EDIT: As I mentioned I would change the class=general_info_content to id=general_info_content1.
function attach(el, event, fnc) {
//attach event to the element
if (el.addEventListener) {
el.addEventListener(event, fnc, false);
}
else if (document.attachEvent) {
el["on" + event] = fnc; // Don not use attachEvent as it breaks 'this'
}
}
function ready() {
// put all your code within $(function(){}); here.
}
function init() {
attach(document, "readystatechange", function () {
if (document.readyState == "complete") {
ready();
}
});
}