I am trying to combine these two functions into one. I know there has to be a really simple way to do it, but everything I have tried so far has not worked. Essentially there are two icons and two menus. When you click one icon a menu either drops down (or raises) depending on the state they are in. Everything after the variables is the same, so it seems to make sense to consolidate them into one shared function. Any help would be greatly appreciated. Thanks!
$(function(){
///Manage Icon 1
$('.ecGlobalNavStudentIcon').click(function(e){
var n = 'hideme'
var m = $('#ecGlobalNavStudentPanel')
var p = $('#ecGlobalNavStaffPanel')
e.preventDefault(); //just prevent the default behavior of the hyperlink
if(m.hasClass(n)) {
console.log($(m).attr('id') + " Has 'hideme' gonna open up");
$(m).show().removeClass(n);
$(m).animate({
height:'49px'
},
500, // Duration
function() { // Callback when the animation is finished
console.log($(m).attr('id') + " Opened!");
});
} else {
console.log($(m).attr('id') + " didn't have 'hideme' gonna try and
close. ");
$(m).animate({
height:'0px'
},
500, // Duration
function() { // Callback when the animation is finished
$(m).hide().addClass(n);
console.log($(m).attr('id') + " Closed!");
});
}
if(!$(p).hasClass(n)) {//open
console.log($(p).attr('id') + " panel open! Gonna close.");
$(p).animate({//close
height:'0px'
},//close
500, // Duration
function() { // Callback when the animation is finished /open
console.log($(p).attr('id') + " Closed by animation!");
$(p).hide().addClass(n);
});//close
}
});
///Manage Icon 2
$('.ecGlobalNavStaffIcon').click(function(e){
var n = 'hideme'
var m = $('#ecGlobalNavStaffPanel')
var p = $('#ecGlobalNavStudentPanel')
e.preventDefault(); //just prevent the default behavior of the hyperlink
if (m.hasClass(n)) {
console.log($(m).attr('id') + " Has 'hideme' gonna open up");
$(m).show().removeClass(n);
$(m).animate({
height: '49px'
},
500, // Duration
function () { // Callback when the animation is finished
console.log($(m).attr('id') + " Opened!");
});
} else {
console.log($(m).attr('id') + " didn't have 'hideme' gonna try and close. ");
$(m).animate({
height: '0px'
},
500, // Duration
function () { // Callback when the animation is finished
$(m).hide().addClass(n);
console.log($(m).attr('id') + " Closed!");
});
}
if (!$(p).hasClass(n)) {//open
console.log($(p).attr('id') + " panel open! Gonna close.");
$(p).animate({//close
height: '0px'
},//close
500, // Duration
function () { // Callback when the animation is finished /open
console.log($(p).attr('id') + " Closed by animation!");
$(p).hide().addClass(n);
});//close
}
});
});
If you want to handle same event for multiple selectors, use the selectors as comma separated.. In your case
$('.ecGlobalNavStudentIcon, .ecGlobalNavStaffIcon').click(function(){
//Your common event handler
});
Always remember, repeating code is evil, a sign of some mistake you've made. And you have done a great job finding it :) Happy coding
It is always good to separate DOM event handling and actual logic.
icon1 click and icon2 click triggers event A
on event A do action A'
consider this example:
$(body).on('togglePanels.my', function (e, activePanel ) {
var panels = $('.panels')
panels.removeClass(cssClass)
activePanel.addClass(cssClass)
})
$(body).on('click','.panelHeader' function(e) {
var $this= $(this)
, panel = $('#' + $this.data('target'))
$(body).trigger('togglePanels.my', [panel])
})
This is pretty much all code you need for accordion you are building, with exception of animation effects
Notice that it requires you to slightly change markup:
common .panel class added for panels
another one .panelHeader for icons
icon has data-target attribute with ID of panel to open.
instead of hide-me class to hide panel, cssClass should hold name of css class to open active one
example markup:
<div>
<i class="panelHeader ecGlobalNavStudentIcon"
data-target="ecGlobalNavStudentPanel">Student</i>
<i class="panelHeader ecGlobalNavStuffIcon"
data-target="ecGlobalNavStaffPanel">Stuff</i>
</div>
<div id='ecGlobalNavStudentPanel'
class="panel ecGlobalNavStudentPanel">...</div>
<div id='ecGlobalNavStaffPanel'
class="panel ecGlobalNavStaffPanel">...</div>
Something like this would work:
$('.ecGlobalNavStudentIcon, .ecGlobalNavStaffIcon').click(function(e){
var n = 'hideme'
var m = $(e.target).hasClass('ecGlobalNavStudentIcon') ? $('#ecGlobalNavStudentPanel') : $('#ecGlobalNavStaffPanel');
var p = $(e.target).hasClass('ecGlobalNavStudentIcon') ? $('#ecGlobalNavStaffPanel') : $('#ecGlobalNavStudentPanel');
$('.ecGlobalNavStaffIcon, ecGlobalNavStaffIcon').click(function(e){
var n = 'hideme';
if this.hasClass('ecGlobalNavStaffIcon'){
var m = $('#ecGlobalNavStudentPanel')
var p = $('#ecGlobalNavStaffPanel')
}
else {
var m = $('#ecGlobalNavStaffPanel')
var p = $('#ecGlobalNavStudentPanel')
}
...
}
if you need, just apply a param and then use the same code (example: $('#'+myParamToSelect).function()
Related
I have a gallery of images that load a vimeo video into an overlay. That part was very easy!!
The more difficult part:
If a user clicks one of the videos, then the remaining videos should automatically load and autoplay until the last video. I have this (almost) working too, (but I may not be doing it in the best way).
And now the trickiest part for me, and my question:
How can I get the last video to stop, and not trigger the on ended event listener?
Here is a pen on codepen I have been working on:
https://codepen.io/mginter/pen/LvMmjK
I have tried forking the logic several ways. I have also tried using the destroy method and rebuild the iframe method (but I can't get the new iframe to show up and put itself into the vacancy left by the destroy method).
I thought if I wrapped the newPlayer.on('ended', function() {}); in a separate function then I could prevent it from triggering, but NO! This is an event listener and it doesn't matter where it is in the code. I have tried turning off the event listener with the newPlayer.off(); method, but apparently I am doing it wrong.
Does anyone out there have any suggestions?? I have been at this for three days with no luck yet.
// Query All Needed Elements
var overlay = document.querySelector("#videomodal");
var iframePlayer = document.querySelector(".iframe-respwrap");
var videoIframe = document.querySelector(".iframe-respwrap iframe");
var newPlayer = new Vimeo.Player(videoIframe);
// Expose the Source Attribute of the iframe
var iframeSrcAtt = videoIframe.src;
// console.log("Iframe Source: " + iframeSrcAtt);
// Get all of the links
var allItems = document.querySelectorAll('.lightbox a');
console.log(allItems + " - Total (NodeList) Length: " + (allItems.length));
// Get source of Last Item in Array
const finalVideoSrc = allItems[allItems.length-1].children[0].dataset.vidsrc;
// Open/Close overlay
function toggleOverlay(state) { overlay.classList.toggle('video-on'); }
function closeOverlay(e) {
overlay.classList.toggle('video-on');
newPlayer.pause().then(function() {newPlayer.unload();}).catch(function(error) { console.log(error); });
}
overlay.addEventListener('click', closeOverlay, false);
// Get initial clicked item source and number
function clickedItem(e) {
e.preventDefault();
let clickedSource = e.target.dataset.vidsrc;
let clickedNumber = parseInt(e.target.parentNode.dataset.number, 10);
startVidLoop(clickedSource, clickedNumber);
}
// ------------------------------------------
// START HERE!! Add Event listener to each link
var z;
for (z=0; z < allItems.length; z++) {
// console.log(allItems[z].children[0].dataset.vidsrc);
allItems[z].addEventListener('click', clickedItem, false);
allItems[z].addEventListener('click', toggleOverlay, false);
}
function startVidLoop(vidSrc, vidNumber) {
if (vidSrc == finalVideoSrc) {
console.log("Incoming: "+ vidSrc + ", Equals Final Video in List: " + finalVideoSrc);
newPlayer.loadVideo(vidSrc).then(function(src) {console.log("END! " + src); newPlayer.play(src);}).catch(function(error) {console.log(error);});
newPlayer.off();
return;
} else {
let nextNumber = vidNumber + 1;
let comingUp = allItems[nextNumber].children[0].dataset.vidsrc;
console.log("Playing Now: "+vidNumber+" - "+vidSrc); console.log("Coming Up: "+nextNumber+" - "+comingUp);
newPlayer.loadVideo(vidSrc).then(function(src) {playVideo(src,comingUp,nextNumber);}).catch(function(error) {console.log(error);});
}
}
function playVideo(vimeoSource,nextVid,nextNumber) {
console.log("Play: " + vimeoSource + " Next: " + nextVid);
newPlayer.play(vimeoSource);
if (nextVid == finalVideoSrc) {
console.log("Last Video is Next!");
nextVid = finalVideoSrc;
}
newPlayer.on('ended', function go(data) {
startVidLoop(nextVid, nextNumber)
});
}
I have this Jquery function to click on an element when its ready. its an interval doing it , the following function:
MonitorAndClick(selector) {
var ele = $(selector);
if (ele.length == 0) {
var intervalid = setInterval(function () {
var ele = $(selector);
if (ele.length > 0) {
ele[0].click();
clearInterval(intervalid);
return true;
}
}, 500);
} else {
ele[0].click();
return true;
}
}
the problem is in some cases , its not working. however this is an interval , and it's checking the element to be ready every 0.5 sec, so how can it be possible ? is there any other way to check the element is ready ?
additional note:
I have an accordion. I have a function to open the accordion->open one of the items->open the tab page in detail section
this is the function :
//--reach to this point, open accordion index 2--------
ShowAccordion(2);
//----open the item with specific Id in accordion items------
setTimeout(function () {
var selector = "tr[gacategory = '/myprotection/mywills/item_" + parseInt(willId) + "]";
MonitorAndClick(selector);
}, 500);
the point is this element SHOULD be there , sometimes its not loading fast enough , and I WANT TO HAVE A WAY TO CHECK IF ITS LOADED, THEN CLICK ON THAT.
Updated code after comments
var selector = "tr[gacategory = '/myprotection/mywills/item_" + parseInt(willId) + "]";
$("#selector").ready(function () {
console.log('**********.... selector is loaded ....*****');
if (!$("#selector").hasClass('selected'))
MonitorAndClick(selector);
});
still not working.
Why do you want to rely on 0.5 seconds delay to make sure your element is present in DOM. You should be invoking this function only after your element is present in the DOM. If there is another condition that drives when this element is added to the DOM, then call this function once that condition is achieved.
You may want to try https://api.jquery.com/ready/
It seems like jquery ready function can be applied on individual elements too
Can anyone tell me why my IF statement is firing before updating the UI with the each loop?
The code basically wants to delay adding css classes to the UI then once each one has been added, redirect the user. It currently just directs immediately?!
$("#logo").click(function() {
//define variables:
var eventDuration = 500;
var elementArray = ['ribbon', 'left-panel', 'wid-id-1', 'wid-id-2'];
var animationArray = ['slideOutRight', 'slideOutLeft', 'rotateOutUpRight', 'rotateOutUpRight'];
//Loop through elements and update UI with timer function:
$.each(elementArray, function(index, value) {
//Increments the delay of the element updates:
var delaytimer = index * eventDuration + eventDuration;
//Adds animation css classes to onpage elements:
$('#' + value).delay(delaytimer).queue(function() {
$(this).addClass('animated ' + animationArray[index]).dequeue();
});
//Once complete redirect to the home page:
if (index === 3) {
$(this).delay(delaytimer + 500).queue(function() {
window.location.replace('/').dequeue;
});
}
});
});
Your if statement is being executed immediately because it isn't inside the delay function. Try moving it in there.
$('#' + value).delay(delaytimer).queue(function() {
$(this).addClass('animated ' + animationArray[index]).dequeue();
//Once complete redirect to the home page:
if (index === 3) {
$(this).delay(delaytimer + 500).queue(function() {
window.location.replace('/').dequeue;
});
}
});
I am using this script from: http://pop.seaofclouds.com/
The problem is if you call the script multiple times it causes a cascading effect of a pop-out within a pop-out for as many times as you call the script.
I'm trying to figure out how to prevent it from executing when the popout has already been set. Here's the script:
//
// pop! for jQuery
// v0.2 requires jQuery v1.2 or later
//
// Licensed under the MIT:
// http://www.opensource.org/licenses/mit-license.php
//
// Copyright 2007,2008 SEAOFCLOUDS [http://seaofclouds.com]
//
(function($) {
$.pop = function(options){
// inject html wrapper
function initpops (){
$(".pop").each(function() {
var pop_classes = $(this).attr("class");
if ( $(this).find('.pop_menu').length) {
// do nothing
} else {
$(this).addClass("pop_menu");
$(this).wrap("<div class='"+pop_classes+"'></div>");
$(".pop_menu").attr("class", "pop_menu");
$(this).before(" \
<div class='pop_toggle'></div> \
");
}
});
}
initpops();
// assign reverse z-indexes to each pop
var totalpops = $(".pop").length + 100;
$(".pop").each(function(i) {
var popzindex = totalpops - i;
$(this).css({ zIndex: popzindex });
});
// close pops if user clicks outside of pop
activePop = null;
function closeInactivePop() {
$(".pop").each(function (i) {
if ($(this).hasClass('active') && i!=activePop) {
$(this).removeClass('active');
}
});
return false;
}
$(".pop").mouseover(function() { activePop = $(".pop").index(this); });
$(".pop").mouseout(function() { activePop = null; });
$("body").on("click", ".pop", function(){
closeInactivePop();
});
// toggle that pop
$("body").on("click", ".pop_toggle", function(){
$(this).parent(".pop").toggleClass("active");
});
}
})(jQuery);
now when i load this script on an ajax call the new pop-out menus work but the old ones do not react to the onclick event.
You shouldn't mess with the plugin. It works exactly like it should.
Better show us how you call this on elements that you already have.
Also I don't like this plugin. Better use something from JqueryUI
You can do such thing in much easier way.
[edit]
I tried your first code (the plugin) and it works correctly for me.
[edit]
OK. I get it. You call $.pop(); multiple times. You shouldn't! Calling $.pop(); will pin up the drop down menu to all elements that has class="pop". This is the reason why you have such funny stack.
Just use $.pop(); once.
Plugin doesn't give ability to connect NEW elements that was dynamically created on the page.
Removed pop from ajax call and just called this on success:
$(".pop").each(function() {
var pop_classes = $(this).attr("class");
if ( $(this).find('.pop_menu').length) {
// do nothing
} else {
$(this).addClass("pop_menu");
$(this).wrap("<div class='"+pop_classes+"'></div>");
$(".pop_menu").attr("class", "pop_menu");
$(this).before(" \
<div class='pop_toggle'></div> \
");
}
});
// assign reverse z-indexes to each pop
var totalpops = $(".pop").length + 100;
$(".pop").each(function(i) {
var popzindex = totalpops - i;
$(this).css({ zIndex: popzindex });
});
// close pops if user clicks outside of pop
activePop = null;
function closeInactivePop() {
$(".pop").each(function (i) {
if ($(this).hasClass('active') && i!=activePop) {
$(this).removeClass('active');
}
});
return false;
}
$(".pop").mouseover(function() { activePop = $(".pop").index(this); });
$(".pop").mouseout(function() { activePop = null; });
is there any way to detect how many seconds a mouse pointer stays on an html element?
I would like to retrieve how many seconds a mouse stays over element to put a little delay on a callback event... if is possible :)
i'm trying with a simple for() cycle detecting by a counter :
var time_over ;
$('.bean-active').live('mouseover',function(){
id_tag = $(this).attr("id");
for(time_over = 1;time_over <= 3000;time_over ++){
if(time_over == 3000){
$('.bean-bubble,.bean-bubble img').hide();
$('#bean-bubble-'+id_tag+',#bean-bubble-'+id_tag+' img').show();
}
}
});
the problem is that it doesn't works :(
also i would like to bind a mouseleave event, script logic should be:
while ( mouseover element count how many time it stays over)
if (time == n)
{ do somenthing }
if (mouseleave from element earlier then time)
{ do somenthing different }
Given this markup:
<div id="hoverOverMe">Hover over me</div>
<div id="output"></div>
Something like this plugin should do the trick:
(function($) {
$.fn.delayedAction = function(options)
{
var settings = $.extend(
{},
{
delayedAction : function(){},
cancelledAction: function(){},
hoverTime: 1000
},
options);
return this.each(function(){
var $this = $(this);
$this.hover(function(){
$this.data('timerId',
setTimeout(function(){
$this.data('hover',false);
settings.delayedAction($this);
},settings.hoverTime));
$this.data('hover',true);
},
function(){
if($this.data('hover')){
clearTimeout($this.data('timerId'));
settings.cancelledAction($this);
}
$this.data('hover',false);
} );
});
}
})(jQuery);
and the calling code:
$('#hoverOverMe').delayedAction (
{
delayedAction: function($element){
$('#output').html($element.attr('id') + ' was hovered for 3 seconds');
},
cancelledAction: function($element){
$('#output').html($element.attr('id') + ' was hovered for less than 3 seconds');
},
hoverTime: 3000 // 3 seconds
}
);
Live example: http://jsfiddle.net/nrUqS/
For your requirement, something like this should suffice:
$('.bean-active').delayedAction(
{
delayedAction: function($element){
id_tag = $element.attr("id");
$('.bean-bubble,.bean-bubble img').hide();
$('#bean-bubble-'+id_tag+',#bean-bubble-'+id_tag+' img').show();
},
hoverTime: 3000
});
This code will calculate the time in milliseconds that you hover over an element with your mouse:
$(document).ready(function() {
$('#element').bind('mouseenter mouseleave', function(evt) {
var currentTime == new Date();
if (evt.type === 'mouseenter') {
$(this).data('mouseenterTime') == currentTime.getTime();
} else if (evt.type === 'mouseleave') {
var mouseoverTime = currentTime.getTime() - $(this).data('mouseenterTime');
alert('mouseover time was: ' + mouseoverTime);
}
})
});
You should be able to utilize the hover() function to capture when the mouse goes over a particular element and then react as desired when the mouse is removed from that object.
$("#someDiv").hover(function(){
//start counter
}, function(){
//stop counter
});
I've used C. Spencer Beggs answer as a template, because his one didn't work for me. I've used simple variables, included lots of console.log messages and corrected '==' code to '='. This example will wait 3 seconds of 'hover over a link' action to take place before acting. HTH someone.
var mouseenterTime = 0;
$(document).on('mouseenter mouseleave', '#element', function (evt)
{
var currentTime = new Date();
if (evt.type === 'mouseenter')
{
mouseenterTime = currentTime.getTime();
console.log('mouseenterTime (#1): ' + mouseenterTime);
} else if (evt.type === 'mouseleave') {
console.log('mouseenterTime (#2): ' + mouseenterTime);
var mouseoverTime = currentTime.getTime() - mouseenterTime;
console.log('mouseover time was: ' + mouseoverTime);
// Checking if the Hover action has latest for longer than 3 seconds.
if(mouseoverTime > 3000) {console.log("Three seconds have elapsed")}
}
})