I'm somewhat new to Javascript. I'm trying to make it so that clicking on an image on one page takes you to a new page and shows a specific div on that new page, so I used sessionStorage to remember and booleans to keep track of which image is being clicked. Right now, the code always executes the first if statement, regardless of which image is clicked. This code works fine in normal java so I can't figure out why my if statements are being ignored in javascript. I also tried adding an 'else' at the end, and tried ===. Here's my javscript, and thank you!
sessionStorage.clickedLeft;
sessionStorage.clickedMiddle;
sessionStorage.clickedRight;
function openedProjectFromGallery() {
if(sessionStorage.clickedLeft) {
$(".left-project-pop-up").show();
} else if (sessionStorage.clickedMiddle) {
$(".middle-project-pop-up").show();
} else if (sessionStorage.clickedRight) {
$(".right-project-pop-up").show();
}
sessionStorage.clickedLeft = false;
sessionStorage.clickedMiddle = false;
sessionStorage.clickedRight = false;
}
$("document").ready(function () {
$(".pop-up .x-button").click(function(){
$(".pop-up").hide();
});
$(".project-description .x-button").click(function(){
$(".project-pop-up").hide();
});
$(".left-project-thumb img").on("click", ".left-project-thumb img", function(){
sessionStorage.clickedLeft = true;
sessionStorage.clickedMiddle = false;
sessionStorage.clickedRight = false;
openedProjectFromGallery();
});
$(".profile-left-project img").click(function(){
$(".left-project-pop-up").show(1000);
});
$(".middle-project-thumb img").on("click", ".middle-project-thumb img", (function(){
sessionStorage.clickedMiddle = true;
sessionStorage.clickedLeft = false;
sessionStorage.clickedRight = false;
openedProjectFromGallery();
});
$(".profile-middle-project img").click(function(){
$(".middle-project-pop-up").show(1000);
});
$(".right-project-thumb img").on("click", ".right-project-thumb img", (function(){
sessionStorage.clickedRight = true;
sessionStorage.clickedLeft = false;
sessionStorage.clickedMiddle = false;
openedProjectFromGallery();
});
$(".profile-right-project img").click(function(){
$(".right-project-pop-up").show(1000);
});
});
You are defining function openedProjectFromGallery() with in document.ready . Define it outside document.ready and also give your three booleans some initial value at the top of your code if not initialized with some value or they are empty. I hope this would help.
It is not really answer to your orginal question,as the main issue with your code is, as #njzk2 says, that openProjectFromGallery only being called once, and not on each event, however I wanted to put my two coins on how this code could look like.
This is good example where custom events should be used
$(document).on('showPopup', function( e, popup ) {
$('.'+popup + '-project-pop-up').show()
})
$(document).on('hidePopup', function( e ) {
$('.popup').hide()
})
$('.left-project-thumb img').on('click', function(e) {
$(document).trigger('showPopup', ['left'])
})
$('.right-project-thumb img').on('click', function(e) {
$(document).trigger('showPopup', ['right'])
})
I think you get an idea.
On the other hand, it always nice to use event delegation with a lot of similar events as well as dom data.
<div class='popup' data-popup='left'>
<img />
</div>
$(document).on('click','.popup', function( e ) {
$(document).trigger('showPopup', [$(this).data('popup')])
})
From what I can see openedProjectFromGallery is only getting called on document load.
Add a call to it into each of the event handling functions or use jQuery's delegate function to assign event handling to each image.
Related
I have this Javascript function for hover items. İt has to work under 958px but its not working. so how can I control that.
But when I resize page up and down, JS stops working.
What's wrong with my function? I am unable to figure it out.
$(document).ready(() => {
if ($(window).width() >958){
$('#group-subscription .owl-item').on('mouseenter', function(){
$(this).nextAll().addClass('has-positive-translate')
$(this).prevAll().addClass('has-negative-translate')
}).on('mouseleave', function() {
removeHasClasses()
})
function removeHasClasses() {
$('#group-subscription .owl-item').removeClass('has-negative-translate has-positive-translate slider-hover-bigger')
}
}
})
Your code is not related to resizing event, it only one time execute when a page is loaded and it is ready, All in all, you should use resize event instead of the ready event.
$(window).on('resize', function(){
var winx = $(this);
if (winx.height() >= 958) {
/* use your code here */
}
});
My code is like this:
$('.flag-icon-dz').click(function() {
var lang = 'Arab';
var $frame = $('.goog-te-menu-frame:first');
if (!$frame.size()) {
console.log("Error: Could not find Google translate frame.");
return false;
}
$frame.contents().find('.goog-te-menu2-item span.text:contains(' + lang + ')').get(0).click();
$("li.ql-item.linkid188546").after("<li class='ql-item linkid18854777 closegoogle'><a href='#' class='btn-primary' target='_self'><i class='icon closegoogle ls-lang-frr' aria-hidden='true'></i></a></li>").fadeIn(500);
$('li.ql-item.linkid188546').fadeOut(500);
return false;
});
$('.closegoogle').click(function() {
$('.skiptranslate').contents().find('.goog-close-link > img').click();
$('li.ql-item.linkid18854777').fadeOut('fast').remove();
$('li.ql-item.linkid188546').fadeIn(500);
});
The first function works great, but the second doesn't. I realize that if I copy/paste the second function in the console after the first one, it works too.
I tried a few solutions (callback / setTimeout / jquery deferred / jquery .when method...) I didn't try promise but I don't think I have to in my context. Maybe I didn't write these solutions good enough.
I finally try to put my event (click) directly the .before() which create my new element like this :
$('.flag-icon-dz').click(function() {
var lang = 'Arab';
var $frame = $('.goog-te-menu-frame:first');
if (!$frame.size()) {
console.log("Error: Could not find Google translate frame.");
return false;
}
$frame.contents().find('.goog-te-menu2-item span.text:contains(' + lang + ')').get(0).click();
$("li.ql-item.linkid188546").after("<li class='ql-item linkid18854777 closegoogle'><a href='#' class='btn-primary' target='_self'><i class='icon closegoogle ls-lang-frr' aria-hidden='true'></i></a></li>").fadeIn(500).click(function() {
$('.skiptranslate').contents().find('.goog-close-link > img').click();
$('li.ql-item.linkid18854777').fadeOut('fast').remove();
$('li.ql-item.linkid188546').fadeIn(500);
});
$('li.ql-item.linkid188546').fadeOut(500);
return false;
});
But it doesn't work either.
Thanks for the help.
EDIT :
I finally found a kind of solution for my second click event (which isn't the best solution but i works) :
window.setInterval(function(){$('.closegoogle').on("click",function(){
$('.skiptranslate').contents().find('.goog-close-link > img').click();
$('li.ql-item.linkid18854777').fadeOut('fast').remove();
$('li.ql-item.linkid188546').fadeIn(500);
}); }, 1000);
Thanks.
You need to use a delegated bind as the element does not exist before you try your binding:
$('#parent-element-of-closegoogle').on('click', '.closegoogle', function() {
$('.skiptranslate').contents().find('.goog-close-link > img').click();
$('li.ql-item.linkid18854777').fadeOut('fast').remove();
$('li.ql-item.linkid188546').fadeIn(500);
});
Please note that the #parent-element-of-closegoogle needs to be an element that already exists when you do the binding - this can be $(document) if you hjave no other element to bind to
I'm using introjs to build a tour of my application. I've searched in quite a few places online and through the documentation but can't seem to find anywhere a method of how to run a function upon skipping or clicking done on the tour. I'm trying to make it so a cookie is stored and the tour isn't run again until a user requests it or a new user comes to the site. Any help would be great, thanks!
$(function(){
var introguide = introJs();
introguide.setOptions({
showProgress: true,
steps: [
{ hidden }
]
});
introguide.start();
});
This code allows to store the tour info
var introguide = introJs();
window.addEventListener('load', function () {
var doneTour = localStorage.getItem('MyTour') === 'Completed';
if (doneTour) {
return;
}
else {
introguide.start()
introguide.oncomplete(function () {
localStorage.setItem('MyTour', 'Completed');
});
introguide.onexit(function () {
localStorage.setItem('MyTour', 'Completed');
});
}
});
Yes, there is a way but with some caveats.
First, after intro.js is loaded you will have a global called introJs with a property fn (standard jquery plug-in approach).
By setting a function using the oncomplete() function under introJS.fn, you can perform some actions when the user hits the 'Done' button.
Here's an example that just displays a console message:
introJs.fn.oncomplete(function() { console.log("Finished"); });
This works as expected. You can put this in a script anytime after the intro.js library is included.
The 'skip' button functionality, however, will only call the 'oncomplete' handler if you are on the last step. The author of the code views that as not complete and so doesn't run that code as you can see by this extract from the code:
skipTooltipButton.onclick = function() {
if (self._introItems.length - 1 == self._currentStep && typeof (self._introCompleteCallback) === 'function') {
self._introCompleteCallback.call(self);
}
_exitIntro.call(self, self._targetElement);
};
This basically says it must be at the last step for this to consider calling the complete callback.
Of course, you could fork the code and remove the restriction. I would suggest if you are going to do that, create a _introSkipCallback in a fashion similar to _introlCompleteCallback and invoke that unless on last step where you might invoke both functions if present.
Hope this helps.
Use oncomplete for functions after 'Done' is clicked
Use onexit for functions after 'Skip' is clicked
Bonus function: onchange will log each step, this can be used to call functions on a particular step
document.getElementById('startButton').onclick = function() {
// log each step
introJs().onchange(function(targetElement) {
console.log(this._currentStep)
if (this._currentStep === 3){
stepThreeFunc()
}
}).start()
// clicking 'Done'
.oncomplete(function(){
someFunc()
})
// clicking 'Skip'
.onexit(function(){
someOtherFunc()
});
};
I've noticed that onexit will be called when you click the done button (which is skip until the last step). onexit does not appear to bind this to the introjs object, so I was able to solve the issue of having onexit called when the walkthrough was completed like this:
// during setup
introJs.oncomplete(handleOnComplete);
introJs.onexit(() => handleOnExit(introJs));
function handleOnComplete() {
console.log(this._currentStep); // this is bound to the introJs object
}
function handleOnExit(introJs) {
const currentStep = introJs._currentStep;
if (currentStep < introJs._options.steps.length) {
doSomethingOnSkip();
}
};
I was going to add a comment, but my rep is too low. I didn't want to answer because I haven't actually tested this, but in version 2.5.0 (maybe previous versions too), there is the onexit function, which I believe is supposed to handle interrupts as well as clicking done at the end. Did you try that?
if ($(".introjs-skipbutton").is(":visible")) {
$( document ).on('click', '.introjs-skipbutton', function(event) {
event.stopPropagation();
event.stopImmediatePropagation();
self.exitTourguide();
});
}
I am using introJS tool in my application to give tour guide information of my application.
I used some functions for handling it dynamically. Here stepsData sending in an array format.
var intro = introJs();
intro.setOptions( {
'nextLabel': 'Next >',
'prevLabel': '< Back',
'tooltipPosition': 'right',
steps: this.stepsData,
showBullets: false,
showButtons: true,
exitOnOverlayClick: false,
keyboardNavigation: true,
} );
hope it will help for handling skip button action.
var self = this; intro.start().onbeforechange( function() { /* skip action*/
if ( $( ".introjs-skipbutton" ).is( ":visible" ) ) {
$( document ).on( 'click', '.introjs-skipbutton', function( event ) {
self.exitTourguide();
});
}
});
skip and done action handling.
/Done click action/
intro.oncomplete( function(){ if ( $( ".introjs-skipbutton" ).is( ":visible" ) ) { $( document ).on( 'click', '.introjs-skipbutton', function( event ) { event.stopPropagation(); event.stopImmediatePropagation(); self.exitTourguide(); }); } });
/* clicking 'Skip' action */ intro.onexit(function(){ if ( $( ".introjs-skipbutton" ).is( ":visible" ) ) { $( document ).on( 'click', '.introjs-skipbutton', function( event ) { event.stopPropagation(); event.stopImmediatePropagation(); self.exitTourguide(); }); } });
I'm trying to run a function twice. Once when the page loads, and then again on click. Not sure what I'm doing wrong. Here is my code:
$('div').each(function truncate() {
$(this).addClass('closed').children().slice(0,2).show().find('.truncate').show();
});
$('.truncate').click(function() {
if ($(this).parent().hasClass('closed')) {
$(this).parent().removeClass('closed').addClass('open').children().show();
}
else if ($(this).parent().hasClass('open')) {
$(this).parent().removeClass('open').addClass('closed');
$('div').truncate();
$(this).show();
}
});
The problem is on line 13 where I call the truncate(); function a second time. Any idea why it's not working?
Edit jsFiddle here: http://jsfiddle.net/g6PLu/
That's a named function literal.
The name is only visible within the scope of the function.
Therefore, truncate doesn't exist outside of the handler.
Instead, create a normal function and pass it to each():
function truncate() { ...}
$('div').each(truncate);
What's the error message do you get?
You should create function and then call it as per requirement
Define the function
function truncate(){
$('div').each(function(){
});
}
Then call the function
truncate();
Another approach is to establish, then trigger, a custom event :
$('div').on('truncate', function() {
$(this).......;
}).trigger('truncate');
Then, wherever else you need the same action, trigger the event again.
To truncate all divs :
$('div').trigger('truncate');
Similarly you can truncate just one particular div :
$('div#myDiv').trigger('truncate');
The only prerequisite is that the custom event handler has been attached, so ...
$('p').trigger('truncate');
would do nothing because a truncate handler has not been established for p elements.
I know there's already an accepted answer, but I think the best solution would be a plugin http://jsfiddle.net/g6PLu/13/ It seems to be in the spirit of what the OP wants (to be able to call $('div').truncate). And makes for much cleaner code
(function($) {
$.fn.truncate = function() {
this.addClass('closed').children(":not('.truncate')").hide().slice(0,2).show();
};
$.fn.untruncate = function() {
this.removeClass('closed').children().show();
};
})(jQuery);
$('div').truncate();
$('.truncate').click(function() {
var $parent = $(this).parent();
if ($parent.hasClass('closed')) {
$parent.untruncate();
} else {
$parent.truncate();
}
});
I am trying to delay the default event or events in a jQuery script. The context is that I want to display a message to users when they perform certain actions (click primarily) for a few seconds before the default action fires.
Pseudo-code:
- User clicks link/button/element
- User gets a popup message stating 'You are leaving site'
- Message remains on screen for X milliseconds
- Default action (can be other than href link too) fires
So far, my attempts look like this:
$(document).ready(function() {
var orgE = $("a").click();
$("a").click(function(event) {
var orgEvent = event;
event.preventDefault();
// Do stuff
doStuff(this);
setTimeout(function() {
// Hide message
hideMessage();
$(this).trigger(orgEvent);
}, 1000);
});
});
Of course, this doesn't work as expected, but may show what I'm trying to do.
I am unable to use plugins as ths is a hosted environment with no online access.
Any ideas?
I would probably do something like this.
$("a").click(function(event) {
event.preventDefault();
doStuff(this);
var url = $(this).attr("href");
setTimeout(function() {
hideMessage();
window.location = url;
}, 1000);
});
I'm not sure if url can be seen from inside the timed function. If not, you may need to declare it outside the click handler.
Edit: If you need to trigger the event from the timed function, you could use something similar to what karim79 suggested, although I'd make a few changes.
$(document).ready(function() {
var slept = false;
$("a").click(function(event) {
if(!slept) {
event.preventDefault();
doStuff(this);
var $element = $(this);
// allows us to access this object from inside the function
setTimeout(function() {
hideMessage();
slept = true;
$element.click(); //triggers the click event with slept = true
}, 1000);
// if we triggered the click event here, it would loop through
// this function recursively until slept was false. we don't want that.
} else {
slept = false; //re-initialize
}
});
});
Edit: After some testing and research, I'm not sure that it's actually possible to trigger the original click event of an <a> element. It appears to be possible for any element other than <a>.
Something like this should do the trick. Add a new class (presumably with a more sensible name than the one I've chosen) to all the links you want to be affected. Remove that class when you've shown your popup, so when you call .click() again your code will no longer run, and the default behavior will occur.
$("a").addClass("fancy-schmancy-popup-thing-not-yet-shown").click(function() {
if ($(this).hasClass("fancy-schmancy-popup-thing-not-yet-shown"))
return true;
doStuff();
$(this).removeClass("fancy-schmancy-popup-thing-not-yet-shown");
var link = this;
setTimeout(function() {
hideMessage();
$(link).click().addClass("fancy-schmancy-popup-thing-not-yet-shown";
}, 1000);
return false;
});
Probably the best way to do this is to use unbind. Something like:
$(document).ready(function() {
$("a").click(function(event) {
event.preventDefault();
// Do stuff
this.unbind(event).click();
});
})
This might work:
$(document).ready(function() {
$("a").click(function(event) {
event.preventDefault();
doStuff(this);
setTimeout(function() {
hideMessage();
$(this).click();
}, 1000);
});
});
Note: totally untested