We have code that spits out several script blocks which add identical functions to the queue that gets called when the document is ready. For example:
$(document).ready(function(){
alert('hey');
});
$(document).ready(function(){
alert('hey');
});
$(document).ready(function(){
alert('hey');
});
This is not causing any problems but of course its unnecessary to call the same code several times.
Without changing the code that generates the repeated blocks, is there a way to make jquery only run the first code block and skip the rest?
Keep in mind that there is the possibility that the ready queue has other functions before and after the repeated code.
I would use an object literal to wrap duplicate code, and set a boolean when it has been called once so it will not be run again:
$(document).ready(function(){
DuplicateHelper.SomeMethod1();
});
$(document).ready(function(){
DuplicateHelper.SomeMethod1();
});
$(document).ready(function(){
DuplicateHelper.SomeMethod1();
});
var DuplicateHelper = {
HasMethod1Run: false,
SomeMethod1: function() {
if (!this.HasMethod1Run) {
// do logic
this.HasMethod1Run = true;
}
}
}
EDIT
You don't have to use the object literal for the code if you are generating the code dynamically, but you can use the same principle with the boolean:
var runCode = true;
$(document).ready(function(){
if (runCode) {
DuplicateHelper.SomeMethod1();
runCode = false;
}
});
$(document).ready(function(){
if (runCode) {
DuplicateHelper.SomeMethod1();
runCode = false;
}
});
$(document).ready(function(){
if (runCode) {
DuplicateHelper.SomeMethod1();
runCode = false;
}
});
However, I agree with netbrain that this situation is indicative of problems elsewhere in the architecture of your solution.
Related
I have some legacy jQuery executing in the page that can't be moved i.e.
jQuery(document).bind('click', function(){
console.log('click');
});
Now that loading of jQuery is at the bottom of the page 'AFTER' the above inline code, the page errors 'jQuery is undefined'
I would like to use a pattern similar to this:
var deferInlineScripts = [];
window.$ = function(inlineFunction) {
deferInlineScripts.push(inlineFunction);
};
Seen working here: https://jsfiddle.net/xpvt214o/165864/
that takes the inline scripts and executes them (Once jQuery is loaded') using
for (i = 0; i < deferInlineScripts.length; i++) {
deferInlineScripts[i]();
}
But unlike the Fiddle my legacy code doesn't have the $(function(){}); and can't be moved, changed or have anything wrapped around it i.e
jQuery(document).bind('click', function(){
console.log('click');
});
jQuery(document).ready(function(){
console.log('ready');
});
Here is the Fiddle https://jsfiddle.net/xpvt214o/165972/ that I would like to fix so the the Bind & Ready functions execute after jQuery is loaded.
Initially define window.jQuery as a function that returns a Proxy. This proxy will allow subsequent arbitrary psuedo-propery lookups (such as .bind in jQuery(document).bind) to be performed. The properties accessed and the arguments the resulting function is eventually called with can be stored in an array and then executed once jQuery is properly loaded.
<script>
const deferCallHandler = {
get: function(jqFirstArg, jqProp) {
return function(...secondArgs) {
deferredInlineScripts.push({
jqFirstArg,
jqProp,
secondArgs,
});
}
}
};
const deferredInlineScripts = [];
window.jQuery = function(jqFirstArg) {
return new Proxy(jqFirstArg, deferCallHandler);
}
document.addEventListener('DOMContentLoaded', function(){
// window.jQuery has now been properly assigned to the true jQuery object
deferredInlineScripts.forEach(({ jqFirstArg, jqProp, secondArgs }) => {
jQuery(jqFirstArg)[jqProp](...secondArgs);
});
});
/* Can't change this code */
jQuery(document).bind('click', function(){
console.log('click');
});
jQuery(document).ready(function(){
console.log('ready');
});
</script>
<div>some element</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm sure this is very simple, but I can't seem to find the answer.
I have a RoR app, and in my application.js file I want to call a function from within a function.
application.js:
jQuery(function_1($) {
$("#select_box").change(function() { ....
....
function_2 ();
return false;
});
jQuery(function_2 () {
...
return false;
);
function 1 is triggered when a select box is changed and works correctly. The issue is that function 2 is executed as soon as a new page is loaded. I only want function 2 to be called from within function 1.
How can I do that?
The problem is that when you put code inside of a block like this:
jQuery(function() {
$("#select_box").change(function() {
function_2();
return false;
});
});
The code is automatically executed. This is equivalent to
$(function() {
});
or
$(document).ready(function() {
});
Which should give you an idea of why function_2 is being invoked on page load. To remedy this, just define the function like this:
jQuery(function() {
var function_2 = function() {
return false;
};
$("#select_box").change(function() {
function_2();
return false;
});
});
See jQuery docs: http://learn.jquery.com/using-jquery-core/document-ready/
If you're using the asset pipeline, you shouldn't have javascript functions in application.js at all, it should just be a manifest. So, assuming you've disabled the asset pipeline, I think you just need to change how you define function_2. Try this:
var function_2 = function () {
...
return false;
};
$("#select_box").change(function() {
....
function_2 ();
return false;
});
function function_2 () {
...
return false;
}
Your question says:
function 1 is triggered when a select box is changed and works correctly. The issue is that function 2 is executed as soon as a new page is loaded. I only want function 2 to be called from within function 1.
$(document).on("change","#select_box",function(e) {
// used on function to incorporate for turbolinks
// your code
// to trigger your function1 when select box is changed
function1 ();
e.preventDefault();
});
function function1(){
//your code
// to trigger your function2 inside function1
function2();
}
function function2(){
//your code
}
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.
What I want to do is I have a code like below :
$(document).ready(
function(){
var currentPage = window.location.pathname;
$('#main-menu-list').find('a[href^="' + currentPage + '"]').closest('li').addClass('active');
}
)
And now I want to add this code to add and get work with other code. I need to add this code after this one:
function () {
/* If there are forms, make all the submit buttons in the page appear
disabled and prevent them to be submitted again to avoid accidental
double clicking. See Issue 980. */
jQuery(function() {
/* Delegate the function to document so it's likely to be the last event
in the queue because of event bubbling. */
jQuery(document).delegate("form", "submit", function (e) {
var form = jQuery(this);
if (form.hasClass("form_disabled")) {
e.preventDefault();
return false;
}
else {
form
.addClass("form_disabled")
.find(":submit")
.addClass("disabled");
}
// Reactivate the forms and their buttons after 3 secs as a fallback.
setTimeout(function () {
form
.removeClass("form_disabled")
.find(":submit")
.removeClass("disabled");
}, 3000);
});
});
}
How can I get this done. Please help me out to solve this problem.
You can create document.ready() anywhere in script. It is not necessary all of your code should be in ready function.
You can create instance variable for function and call it where you need:
$(document).ready(
var myFunc = function(){
var currentPage = window.location.pathname;
//other code
}
...
//and invoke it where you need
myFunc();
)
First, name the long function in your code section, for example, launchFormControls(). And then define the function outside of the document ready event. A good practice would be to do so and keep the ready event body clean.
For example:
function launchFormControls() {
//function code
}
Or, in other syntax:
var launchFormControls = function() {
//function code
}
Second, call your function from within the document ready event. Your function will be defined and able to call once the document is loaded. This code can be placed at the top or bottom of your javascript section or file.
For example:
$(document).ready(function(){
var currentPage = window.location.pathname;
$('#main-menu-list').find('a[href^="' + currentPage+'"]').closest('li').addClass('active');
launchFormControls();
});
I have a jQuery function that uses ajax to get data, then displays it, I want to use an if statement to determine if the function has already been run, if it has, a certain section of the function doesn't run again, for some reason, the if statement is being ignored.
This is my code:
<script type="text/javascript">
var a = 1;
$(function() {
if(a<2) {
$('.notifications').click(function() {
$('#notifications2').show();
$('#loader').show();
$.get('/getnotifications.php', function(data) {
$(".getnot").append(data);
$('#loader').hide();
a++;
});
});
}
});
</script>
Any idea why this is failing to work?
You're placing the if statement at the wrong point, try this:
<script type="text/javascript">
var a = 1;
$(function() {
$('.notifications').click(function() {
if(a<2) {
$('#notifications2').show();
$('#loader').show();
$.get('/getnotifications.php', function(data) {
$(".getnot").append(data);
$('#loader').hide();
a++;
});
}
});
});
</script>
You're current code is simply checking that a is less than 2 when the document first loads, not every time you click on .notifications.