Run a "non" click function within another function only once - javascript

How do I run a function only once? I read about jquery .one but it seems to only work with click functions. I need my audio play function to activate only once otherwise I have two audio players when the user clicks on the same link again.
How would I do this? Here is piece of code I need running once:
$(function() {
$('audio').audioPlayer();
});
and here the full code:
$('ul li:nth-child(2)').click(function(e) {;
e.preventDefault();
link1.reverse()
link2.reverse()
link3.reverse()
$('#div').uncomment( /* recurse */ true);
setTimeout(function() {
link4.play()
$(function() {
$('audio').audioPlayer();
});
picturefill({
reevaluate: true
});
},

You could simply use a variable to track whether or not it has been executed. And you don't need the $(function() {...} inside the setTimeout function as this binding is already going to be created after the DOM is ready.
E.g.
HTML:
<ul>
<li>test</li>
<li>click me</li>
<li>test</li>
</ul>
JS:
var hasPlayed = false;
$(function () {
$('ul li:nth-child(2)').click(function (e) {;
e.preventDefault();
link1.reverse();
link2.reverse();
link3.reverse();
$('#div').uncomment( /* recurse */ true);
if (!hasPlayed) {
hasPlayed = true;
setTimeout(function () {
link4.play();
$('audio').audioPlayer();
picturefill({
reevaluate: true
});
}, 1000);
}
});
});
Fiddle: http://jsfiddle.net/BenjaminRay/2eaf28jh/

Try using data attributes,
var playAudio = function() {
if ($('.audio').data('once') != true) {
$('.audio').append('Once'); // replace with $('audio').audioPlayer();
$('.audio').data('once', true)
}
};
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="audio"></div>
Click Me

You could use a guard condition. I'm not that familiar with this audioPlayer(), but if there is a way to ask "is it playing" you could do
if (!audioPlayer.isPlaying()) {
$('audio').audioPlayer();
}
Otherwise you could do something like
//Outside the click handler
var isFirstRun = true;
...
//Inside the click handler
if (isFirstRun) {
isFirstRun = false;
$('audio').audioPlayer();
}

Related

how to run all functions in one click

I want help in solving this problem
I want to run all functions in one click how can I do this
Is the code of jquery
/*global $*/
$(function () {
'use strict';
$(".click1 button").on("click", function click1() {
$(this).parent(".click1").css("background-color", "#f00");
});
$(".click2 button").on("click", function click2() {
$(this).parent(".click2").css("background-color", "#ff0");
});
$(".click3 button").on("click", function click3() {
$(this).parent(".click3").css("background-color", "#f0f");
});
$("clickAll").on("click", function () {
click1();
click2();
click3();
});
});
You can use trigger function.
/*global $*/
$(function () {
'use strict';
$(".click1 button").on("click", function click1() {
$(this).parent(".click1").css("background-color", "#f00");
});
$(".click2 button").on("click", function click2() {
$(this).parent(".click2").css("background-color", "#ff0");
});
$(".click3 button").on("click", function click3() {
$(this).parent(".click3").css("background-color", "#f0f");
});
$("clickAll").on("click", function () {
$(".click1 button").trigger("click");
$(".click2 button").trigger("click");
$(".click3 button").trigger("click");
});
});
Use .triggerHandler to fire the event without bubbling:
/*global $*/
$(function() {
'use strict';
var clickMe = function(event, parent, bgColor) {
$(event.target).parent(parent).css("background-color", bgColor);
};
var $click1Button = $(".click1 button");
$click1Button.on("click", function(event) {
clickMe(event, ".click1", "#f00");
});
var $click2Button = $(".click2 button");
$click2Button.on("click", function(event) {
clickMe(event, ".click2", "#ff0");
});
var $click3Button = $(".click3 button");
$click3Button.on("click", function(event) {
clickMe(event, ".click3", "#f0f");
});
$(".clickAll").on("click", function() {
$click1Button.triggerHandler("click");
$click2Button.triggerHandler("click");
$click3Button.triggerHandler("click");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="click1"><button>click1</button></div>
<div class="click2"><button>click2</button></div>
<div class="click3"><button>click3</button></div>
<div class="clickAll"><button>clickAll</button></div>
Since the code executed in each handler is slightly the same, you can use event delegation to reduce the code required and moving what's related to the view in your html markup.
$(function(){
$("#common_ancestor").on('click', function (evt){
let $button = $(evt.target)
// Depending on your markup, you way use closest() or parents() instead of parent() here.
, $parent = $button.parent()
, clickSelector = '[class*="click"]'
;
// Test which button was triggered based on its parent
if ($parent.is('.clickAll')) {
$(this).find(clickSelector).each(function() {
this.style.backgroundColor = $(this).data('color');
})
} else if ($parent.is(clickSelector)) {
$parent[0].style.backgroundColor = $parent.data('color');
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="common_ancestor">
<div class="click1" data-color="#f00"><button>click1</button></div>
<div class="click2" data-color="#ff0"><button>click2</button></div>
<div class="click3" data-color="#f0f"><button>click3</button></div>
<div class="clickAll"><button>clickAll</button></div>
</div>
Pros on using event delegation:
You don't need to register listener again when injecting additionnal <div class="clickn" data-color="#ff0"><button>clickn</button></div> elements in "#common_ancestor" div.
Only one function object is created in memory.
Cons:
- If you have non trivial behavior or code that differs slightly between targes, your uniq handler might quickly become bloated, which might affect code readability a lot in the long term.

toggle functions called on click of element?

Why when I first click on the span does it call function a and b,
how do I make it so it calls function a on first click and on second click it calls function b?
function a(id) {
$.post("url.php", {'id':id}, function() {
$(".aa"+id).removeAttr('onclick');
$(".aa"+id).attr('onclick', b(id);
);
}
function b(id) {
$.post("url.php", {'id':id}, function() {
$(".aa"+id).removeAttr('onclick');
$(".aa"+id).attr('onclick', a(id);
);
}
<span class="aa '.$item['id'].'" onclick="a(' . $item['id'] . ')">A</span>
You can achieve this much more simply by attaching your events using Javascript and toggling a class to determine which function should be called. Try this:
<span class="a toggle" data-id="'.$item['id'].'">A</span>
$(function() {
$('.toggle').click(function() {
$(this).toggleClass('a b');
});
$(document).on('click', '.toggle.a', function() {
var $el = $(this);
$.post("url.php", { id: $el.data('id') }, function() {
// do something when .a clicked...
});
});
$(document).on('click', '.toggle.b', function() {
var $el = $(this);
$.post("url.php", { id: $el.data('id') }, function() {
// do something when .b clicked...
});
});
});
Example fiddle
I presume the logic of your actual a() and b() functions in your production code is different...
You can use $.data() to store which function got executed and by taking reference of it, you can call required function like below:
function a() {
alert("function A");
}
function b() {
alert("function B");
}
$(document).ready(function(){
$("span.aa").click(function(){
var prevCalledFunction = $(this).data("function");
if(prevCalledFunction == null || prevCalledFunction == "B"){
a();
$(this).data("function","A");
}
else{
b();
$(this).data("function","B");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<span class="aa">A</span>
do something like this, simply set an attribute on the span element to show if it has been clicked for the first time and if yes it selects the second function you want. Then Assume after the second click, the third click should go back to first function and so on.
$(document).ready(function() {
$("span.aa").click(function() {
//checking if the span has been clicked before since the page was loaded via if it has the attribute "checked_before"
if ($(this).is('[check_before]') == false) {
alert("Just called function a");
//a(id);
$(this).attr("check_before", "true");
} else if ($(this).is('[check_before]') == true) {
alert("just called function b");
//b(id);
$(this).removeAttr("check_before");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.0/jquery.min.js"></script><span class='aa'>Click me </span>

Alert button's inner content after clicking it

Please, help fix bug: the code currently alerts undefined instead of button's inner contents
function registerClickHandler() {
$('#clickme').click(function() {
setTimeout(function() {
alert(this.innerHTML);
}, 200);
});
}
this inside the timeout handler is not the button
function registerClickHandler() {
$('#clickme').click(function (e) {
setTimeout(function () {
alert(e.currentTarget.innerHTML);
}, 200);
});
}
Try to get the value before setTimeout
function registerClickHandler() {
$('#clickme').click(function () {
var value=this.innerHTML;
setTimeout(function () {
alert(value);
}, 200);
});
}
In java script this points to the last function and inside the timeout handler is not the button, thats why you are getting the error.
Also it's a good practice implement this kind of functions or onclicks using on.('click', function(){...})
below you can see my example:
$(document).ready(function(){
$('#clickme').on('click', function (e) {
setTimeout(function() {
alert(e.currentTarget.innerHTML);
}, 200);
});
});
You can take a look and run it here: http://jsfiddle.net/gon250/6qwk0g1t/1/
Try putting the click eventhandler outside the function. Also pass the value of 'this' to a variable before calling setTimout. Later use this variable inside setTimout. Read more about Javascrpt prototypes here
$(document).ready(function(){
$('#clickme').click(function() {
var me = this;
setTimeout(function() {
alert(me.innerHTML);
}, 200);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="clickme">click me</div>

Function becomes undefined after first trigger

I have a block of code like so:
function doSomething() {
someVar.on("event_name", function() {
$('#elementId').click(function(e) {
doSomething();
});
});
}
// and on document ready
$(function () {
$('#anotherElemId').click(function () {
doSomething();
});
});
The problem that I'm encountering is that when I call doSomething() from anotherElemId click event(that is binded on document ready) it works as expected, but calling it recursively from elementId click doesn't work.
Any ideas? Thinking is something trivial that I'm missing.
Is someVar an actual jQuery reference to a dom element? (e.g. $('#someitem'))
The second problem is you cant put a .click event inside a function that you would like to instantiate later on. If you are trying to only allow #elementId to have a click event AFTER some previous event, try testing if a tester variable is true:
var activated = false;
$(function () {
$('#anotherElemId').click(function () {
activated = true;
});
$('#secondElemId').on("event_name", function() {
if (activated) {
// code that happens only after #anotherElemId was clicked.
}
});
});

jQuery event to trigger action when a div is made visible

I'm using jQuery in my site and I would like to trigger certain actions when a certain div is made visible.
Is it possible to attach some sort of "isvisible" event handler to arbitrary divs and have certain code run when they the div is made visible?
I would like something like the following pseudocode:
$(function() {
$('#contentDiv').isvisible(function() {
alert("do something");
});
});
The alert("do something") code should not fire until the contentDiv is actually made visible.
Thanks.
You could always add to the original .show() method so you don't have to trigger events every time you show something or if you need it to work with legacy code:
Jquery extension:
jQuery(function($) {
var _oldShow = $.fn.show;
$.fn.show = function(speed, oldCallback) {
return $(this).each(function() {
var obj = $(this),
newCallback = function() {
if ($.isFunction(oldCallback)) {
oldCallback.apply(obj);
}
obj.trigger('afterShow');
};
// you can trigger a before show if you want
obj.trigger('beforeShow');
// now use the old function to show the element passing the new callback
_oldShow.apply(obj, [speed, newCallback]);
});
}
});
Usage example:
jQuery(function($) {
$('#test')
.bind('beforeShow', function() {
alert('beforeShow');
})
.bind('afterShow', function() {
alert('afterShow');
})
.show(1000, function() {
alert('in show callback');
})
.show();
});
This effectively lets you do something beforeShow and afterShow while still executing the normal behavior of the original .show() method.
You could also create another method so you don't have to override the original .show() method.
The problem is being addressed by DOM mutation observers. They allow you to bind an observer (a function) to events of changing content, text or attributes of dom elements.
With the release of IE11, all major browsers support this feature, check http://caniuse.com/mutationobserver
The example code is a follows:
$(function() {
$('#show').click(function() {
$('#testdiv').show();
});
var observer = new MutationObserver(function(mutations) {
alert('Attributes changed!');
});
var target = document.querySelector('#testdiv');
observer.observe(target, {
attributes: true
});
});
<div id="testdiv" style="display:none;">hidden</div>
<button id="show">Show hidden div</button>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
There is no native event you can hook into for this however you can trigger an event from your script after you have made the div visible using the .trigger function
e.g
//declare event to run when div is visible
function isVisible(){
//do something
}
//hookup the event
$('#someDivId').bind('isVisible', isVisible);
//show div and trigger custom event in callback when div is visible
$('#someDivId').show('slow', function(){
$(this).trigger('isVisible');
});
You can use jQuery's Live Query plugin.
And write code as follows:
$('#contentDiv:visible').livequery(function() {
alert("do something");
});
Then everytime the contentDiv is visible, "do something" will be alerted!
redsquare's solution is the right answer.
But as an IN-THEORY solution you can write a function which is selecting the elements classed by .visibilityCheck (not all visible elements) and check their visibility property value; if true then do something.
Afterward, the function should be performed periodically using the setInterval() function. You can stop the timer using the clearInterval() upon successful call-out.
Here's an example:
function foo() {
$('.visibilityCheck').each(function() {
if ($(this).is(':visible')){
// do something
}
});
}
window.setInterval(foo, 100);
You can also perform some performance improvements on it, however, the solution is basically absurd to be used in action. So...
The following code (pulled from http://maximeparmentier.com/2012/11/06/bind-show-hide-events-with-jquery/) will enable you to use $('#someDiv').on('show', someFunc);.
(function ($) {
$.each(['show', 'hide'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
this.trigger(ev);
return el.apply(this, arguments);
};
});
})(jQuery);
If you want to trigger the event on all elements (and child elements) that are actually made visible, by $.show, toggle, toggleClass, addClass, or removeClass:
$.each(["show", "toggle", "toggleClass", "addClass", "removeClass"], function(){
var _oldFn = $.fn[this];
$.fn[this] = function(){
var hidden = this.find(":hidden").add(this.filter(":hidden"));
var result = _oldFn.apply(this, arguments);
hidden.filter(":visible").each(function(){
$(this).triggerHandler("show"); //No bubbling
});
return result;
}
});
And now your element:
$("#myLazyUl").bind("show", function(){
alert(this);
});
You could add overrides to additional jQuery functions by adding them to the array at the top (like "attr")
a hide/show event trigger based on Glenns ideea:
removed toggle because it fires show/hide and we don't want 2fires for one event
$(function(){
$.each(["show","hide", "toggleClass", "addClass", "removeClass"], function(){
var _oldFn = $.fn[this];
$.fn[this] = function(){
var hidden = this.find(":hidden").add(this.filter(":hidden"));
var visible = this.find(":visible").add(this.filter(":visible"));
var result = _oldFn.apply(this, arguments);
hidden.filter(":visible").each(function(){
$(this).triggerHandler("show");
});
visible.filter(":hidden").each(function(){
$(this).triggerHandler("hide");
});
return result;
}
});
});
I had this same problem and created a jQuery plugin to solve it for our site.
https://github.com/shaunbowe/jquery.visibilityChanged
Here is how you would use it based on your example:
$('#contentDiv').visibilityChanged(function(element, visible) {
alert("do something");
});
What helped me here is recent ResizeObserver spec polyfill:
const divEl = $('#section60');
const ro = new ResizeObserver(() => {
if (divEl.is(':visible')) {
console.log("it's visible now!");
}
});
ro.observe(divEl[0]);
Note that it's crossbrowser and performant (no polling).
Just bind a trigger with the selector and put the code into the trigger event:
jQuery(function() {
jQuery("#contentDiv:hidden").show().trigger('show');
jQuery('#contentDiv').on('show', function() {
console.log('#contentDiv is now visible');
// your code here
});
});
Use jQuery Waypoints :
$('#contentDiv').waypoint(function() {
alert('do something');
});
Other examples on the site of jQuery Waypoints.
I did a simple setinterval function to achieve this. If element with class div1 is visible, it sets div2 to be visible. I know not a good method, but a simple fix.
setInterval(function(){
if($('.div1').is(':visible')){
$('.div2').show();
}
else {
$('.div2').hide();
}
}, 100);
You can also try jQuery appear plugin as mentioned in parallel thread https://stackoverflow.com/a/3535028/741782
This support easing and trigger event after animation done! [tested on jQuery 2.2.4]
(function ($) {
$.each(['show', 'hide', 'fadeOut', 'fadeIn'], function (i, ev) {
var el = $.fn[ev];
$.fn[ev] = function () {
var result = el.apply(this, arguments);
var _self=this;
result.promise().done(function () {
_self.triggerHandler(ev, [result]);
//console.log(_self);
});
return result;
};
});
})(jQuery);
Inspired By http://viralpatel.net/blogs/jquery-trigger-custom-event-show-hide-element/
There is a jQuery plugin available for watching change in DOM attributes,
https://github.com/darcyclarke/jQuery-Watch-Plugin
The plugin wraps All you need do is bind MutationObserver
You can then use it to watch the div using:
$("#selector").watch('css', function() {
console.log("Visibility: " + this.style.display == 'none'?'hidden':'shown'));
//or any random events
});
Hope this will do the job in simplest manner:
$("#myID").on('show').trigger('displayShow');
$('#myID').off('displayShow').on('displayShow', function(e) {
console.log('This event will be triggered when myID will be visible');
});
I changed the hide/show event trigger from Catalint based on Glenns idea.
My problem was that I have a modular application. I change between modules showing and hiding divs parents. Then when I hide a module and show another one, with his method I have a visible delay when I change between modules. I only need sometimes to liten this event, and in some special childs. So I decided to notify only the childs with the class "displayObserver"
$.each(["show", "hide", "toggleClass", "addClass", "removeClass"], function () {
var _oldFn = $.fn[this];
$.fn[this] = function () {
var hidden = this.find(".displayObserver:hidden").add(this.filter(":hidden"));
var visible = this.find(".displayObserver:visible").add(this.filter(":visible"));
var result = _oldFn.apply(this, arguments);
hidden.filter(":visible").each(function () {
$(this).triggerHandler("show");
});
visible.filter(":hidden").each(function () {
$(this).triggerHandler("hide");
});
return result;
}
});
Then when a child wants to listen for "show" or "hide" event I have to add him the class "displayObserver", and when It does not want to continue listen it, I remove him the class
bindDisplayEvent: function () {
$("#child1").addClass("displayObserver");
$("#child1").off("show", this.onParentShow);
$("#child1").on("show", this.onParentShow);
},
bindDisplayEvent: function () {
$("#child1").removeClass("displayObserver");
$("#child1").off("show", this.onParentShow);
},
I wish help
One way to do this.
Works only on visibility changes that are made by css class change, but can be extended to watch for attribute changes too.
var observer = new MutationObserver(function(mutations) {
var clone = $(mutations[0].target).clone();
clone.removeClass();
for(var i = 0; i < mutations.length; i++){
clone.addClass(mutations[i].oldValue);
}
$(document.body).append(clone);
var cloneVisibility = $(clone).is(":visible");
$(clone).remove();
if (cloneVisibility != $(mutations[0].target).is(":visible")){
var visibilityChangedEvent = document.createEvent('Event');
visibilityChangedEvent.initEvent('visibilityChanged', true, true);
mutations[0].target.dispatchEvent(visibilityChangedEvent);
}
});
var targets = $('.ui-collapsible-content');
$.each(targets, function(i,target){
target.addEventListener('visibilityChanged',VisbilityChanedEventHandler});
target.addEventListener('DOMNodeRemovedFromDocument',VisbilityChanedEventHandler });
observer.observe(target, { attributes: true, attributeFilter : ['class'], childList: false, attributeOldValue: true });
});
function VisbilityChanedEventHandler(e){console.log('Kaboom babe'); console.log(e.target); }
my solution:
; (function ($) {
$.each([ "toggle", "show", "hide" ], function( i, name ) {
var cssFn = $.fn[ name ];
$.fn[ name ] = function( speed, easing, callback ) {
if(speed == null || typeof speed === "boolean"){
var ret=cssFn.apply( this, arguments )
$.fn.triggerVisibleEvent.apply(this,arguments)
return ret
}else{
var that=this
var new_callback=function(){
callback.call(this)
$.fn.triggerVisibleEvent.apply(that,arguments)
}
var ret=this.animate( genFx( name, true ), speed, easing, new_callback )
return ret
}
};
});
$.fn.triggerVisibleEvent=function(){
this.each(function(){
if($(this).is(':visible')){
$(this).trigger('visible')
$(this).find('[data-trigger-visible-event]').triggerVisibleEvent()
}
})
}
})(jQuery);
example usage:
if(!$info_center.is(':visible')){
$info_center.attr('data-trigger-visible-event','true').one('visible',processMoreLessButton)
}else{
processMoreLessButton()
}
function processMoreLessButton(){
//some logic
}
$( window ).scroll(function(e,i) {
win_top = $( window ).scrollTop();
win_bottom = $( window ).height() + win_top;
//console.log( win_top,win_bottom );
$('.onvisible').each(function()
{
t = $(this).offset().top;
b = t + $(this).height();
if( t > win_top && b < win_bottom )
alert("do something");
});
});
$(function() {
$(document).click(function (){
if ($('#contentDiv').is(':visible')) {
alert("Visible");
} else {
alert("Hidden");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="contentDiv">Test I'm here</div>
<button onclick="$('#contentDiv').toggle();">Toggle the div</button>
<div id="welcometo">Özhan</div>
<input type="button" name="ooo"
onclick="JavaScript:
if(document.all.welcometo.style.display=='none') {
document.all.welcometo.style.display='';
} else {
document.all.welcometo.style.display='none';
}">
This code auto control not required query visible or unvisible control

Categories

Resources