I want to be able to put the code in one place and call it from several different events.
Currently I have a selector and an event:
$("input[type='checkbox']").on('click', function () {
// code works here //
});
I use the same code elsewhere in the file, however using a different selector.
$(".product_table").on('change', '.edit_quantity', function () {
// code works here //
});
I have tried following the advice given elsewhere on StackOverflow, to simply give my function a name and then call the named function but that is not working for me. The code simply does not run.
$(".product_table").on('change', '.edit_quantity', function () {
calculateTotals() {
// code does not work //
}
});
So, I tried putting the code into it's own function separate from the event and call it inside the event, and that is not working for me as well.
calculateTotals() {
// code does not work //
}
So what am I doing wrong ?
You could pass your function as a variable.
You want to add listeners for events after the DOM has loaded, JQuery helps with $(document).ready(fn); (ref).
To fix your code:
$(document).ready(function() {
$("input[type='checkbox']").on('click', calculateTotalsEvent)
$(".product_table").on('change', '.edit_quantity', calculateTotalsEvent)
});
function calculateTotalsEvent(evt) {
//do something
alert('fired');
}
Update:
Vince asked:
This worked for me - thank you, however one question: you say, "pass your function as a variable" ... I don't see where you are doing this. Can you explain ? tks. – Vince
Response:
In JavaScript you can assign functions to variables.
You probably do this all the time when doing:
function hello() {
//
}
You define window.hello.
You are adding to Global Namespace.
JavaScript window object
This generally leads to ambiguous JavaScript architecture/spaghetti code.
I organise with a Namespace Structure.
A small example of this would be:
app.js
var app = {
controllers: {}
};
You are defining window.app (just a json object) with a key of controllers with a value of an object.
something-ctlr.js
app.controllers.somethingCtlr.eventName = function(evt) {
//evt.preventDefault?
//check origin of evt? switch? throw if no evt? test using instanceof?
alert('hi');
}
You are defining a new key on the previously defined app.controllers.somethingCtlrcalled eventName.
You can invoke the function with ();.
app.controllers.somethingCtlr.eventName();
This will go to the key in the object, and then invoke it.
You can pass the function as a variable like so.
anotherFunction(app.controllers.somethingCtlr.eventName);
You can then invoke it in the function like so
function anotherFunction(someFn) { someFn();}
The javascript files would be structured like so:
+-html
+-stylesheets
+-javascript-+
+-app-+
+-app.js
+-controllers-+
+-something-ctlr.js
Invoke via chrome developer tools with:
app.controllers.somethingCtlr.eventName();
You can pass it as a variable like so:
$(document).ready(function() {
$('button').click(app.controllers.somethingCtlr.eventName);
});
JQuery (ref).
I hope this helps,
Rhys
It looks like you were on the right track but had some incorrect syntax. No need for { } when calling a function. This code should behave properly once you add code inside of the calculateTotals function.
$(".product_table").on('change', '.edit_quantity', function () {
calculateTotals();
});
$("input[type='checkbox']").on('click',function() {
calculateTotals();
});
function calculateTotals() {
//your code...
}
You could just condense it all into a single function. The onchange event works for both the check box and the text input (no need for a click handler). And jQuery allows you to add multiple selectors.
$('input[type=checkbox], .product_table .edit_quantity').on('change', function() {
console.log('do some calculation...');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="product_table">
<input type="checkbox">
<input class="edit_quantity">
</div>
Related
We have this tag with a javascript function in our HTML,
<select name="My_Saved_Billing" onchange="Choose_My_Saved_Billing(this.selectedIndex)" >
<option>Select</option>
<option value="1714">Address line 1, QC</option>
</select>
<script type="text/javascript">
function Choose_My_Saved_Billing(arg_index) {
switch(arg_index) {
// some commands here
}
}
</script>
And I also added a jQuery to it which is below so that on windows load, it will automatically select the second option.
<script type="text/javascript">
$(window).load(function(){
$("select").val($("select option:eq(1)").val());
});
</script>
But is it possible to call javascript function using jQuery? If so, how should I call this one?
Should I use Choose_My_Saved_Billing(this.selectedIndex)or Choose_My_Saved_Billing(arg_index)or you might know something. I've tried these two but none are working. Please let me know. Just a beginner here.
The way to call a JavaScript function from a JQuery file is the same as calling a JavaScript function from a JavaScript file :) This is so because JQuery is a library based from JavaScript. Say, you want to call function foo from a JavaScript file, when the window loads.
JQuery:
$(window).on('load', function() {
foo();
});
And JavaScript:
function foo() {
alert('This works!');
}
I hope this helps!
Yes, it's possible to call functions inside a jQuery ready block. Since you've defined the function at global scope (should probably move this into the jQuery ready block or, if you want to go to the trouble, into a module), it can be called from anywhere. So inside your ready block:
$(function () {
// do stuff
Choose_My_Saved_Billing(args);
});
jQuery is JavaScript. It's just a library for JavaScript. The main jQuery global $ is a JavaScript function that takes a valid selector as an argument and provides several methods on the return value of that function.
So calling a JavaScript function inside the callback function to .load is not an issue.
It is not clear what the Choose_My_Saved_Billing function actually does.
Think about what's happening here. In your onchange event you're calling the function with the index of the selected option passed as an argument. Since JQuery is just a library of shortcuts for things you can do in JavaScript, we should easily be able to do the same thing.
So let's get the element for which we want the selected index:
// maybe think about adding an ID here for better selection
var select = $('select[name^="My_Saved_"]');
Then let's get the index with a change event, then call the function:
var index = 0;
select.change(function(){
index = select.selectedIndex || 2; // set the index to default to 2
Choose_My_Saved_billing(index);
});
Instead of using onchange="...", just use jQuery to attach a change listener:
$(window).load(function() {
$('.colors_backgroundneutral select').on('change', function () {
Choose_My_Saved_Billing(this.value);
});
});
$(document).ready(function() {
$("#Submit1").click(function() {
$("#id1").hide();
Raise1();
});
$("#Raise").click(function() {
$("#id1").show();
});
});
function Raise1() {
var value1;
alert("hi");
value1 = document.getElementById("amount").value;
alert(value1);
alert("done");
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.0.1/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.1/jquery.min.js"></script>
As jQuery is a more simple and advanced JavaScript solution, my guessing is you can call you JS function like this:
$(window).load(function(){
my_js_function(arg1, arg2);
});
Now, what you want is to call the JS function named Choose_My_Saved_Billing() with argument arg_index
So, your jQuery will look like this:
$(window).load(function(){
Choose_My_Saved_Billing(arg_index);
});
This only works if the function is already declared through raw code, on via the <script type="text/javascript" src="path/to/my_file.js"> head tag.
It should work like a charm, if not, feel free to share the errors returned by your browser.
I have created a javascript file that contains the following:
(function ($) {
//Define a Drupal behaviour with a custom name
Drupal.behaviors.jarrowDynamicTextfieldValidator = {
attach: function (context) {
//Add an eventlistener to the document reacting on the
//'clientsideValidationAddCustomRules' event.
$(document).bind('clientsideValidationAddCustomRules', function(event){
//Add your custom method with the 'addMethod' function of jQuery.validator
//http://docs.jquery.com/Plugins/Validation/Validator/addMethod#namemethodmessage
jQuery.validator.addMethod("typeValidator", function(value, element, param) {
...bunch of code here...
}, jQuery.format('Field can not be empty'));
});
}
};
})(jQuery);
What I would like to do is add an change listener to a select box so that when the selection changes it would call this validation function. I am not sure if I can do this since the validation code is buried within several functions. Is this possible?
the way your original code is showing it, no, you wouldn't be able to call any of those functions because they're anonymous and are within the scope of the parent functions.
If you were to declare a variable for the function outside of the function that calls it, then you'd be able to reuse the function, because it will be global to the scope of the other function. Note: if you wanted the variable to be completely global, or rather, have it be accessible no matter where you are in the code, just don't write the var in front of the variable, it will then be "global", which is actually the equivalent of putting the variable within the window namespace.
Here's an example of that, using your code:
(function ($) {
var customCallback = function(event){
//Add your custom method with the 'addMethod' function of jQuery.validator
//http://docs.jquery.com/Plugins/Validation/Validator/addMethod#namemethodmessage
jQuery.validator.addMethod("typeValidator", function(value, element, param) {
...bunch of code here...
}, jQuery.format('Field can not be empty'));
};
//Define a Drupal behaviour with a custom name
Drupal.behaviors.jarrowDynamicTextfieldValidator = {
attach: function (context) {
//Add an eventlistener to the document reacting on the
//'clientsideValidationAddCustomRules' event.
$(document).bind('clientsideValidationAddCustomRules', customCallback);
}
};
//now you can use that function again...
$('#something').on('someEvent', customCallback );
})(jQuery);
Please note that you'll have to make some adjustments to that function to make sure all of your variables are available and things like that due to variable scope. So, this may need some tweaking to make it work for your scenario.
Normally you wouldn't be able to call that anonymous function without modifying the code a little, however that seems to be the way of registering custom validation rules for the jQuery Validation Plugin and once registered, you can definitely use that custom rule through the plugin's API.
For instance, the following code adds a custom rule:
jQuery.validator.addMethod("typeValidator", function(value, element, param) {
...bunch of code here...
}, jQuery.format('Field can not be empty'));
Now you can initialize the plugin on your form and call the valid function to validate the form.
$('#someForm').validate({
rules: {
someField: {
typeValidator: true //use the custom validation rule
}
}
});
Now you can check if the form is valid using $('#someForm').valid().
Have a look at the plugin's API for more infos.
Below is the code that I used for multiple java scripts on a single button. But only any one is working when I disable the second one. Please let me know: how do I change my code to make it to work fine?
function invoke(but)
{
if(but==0)
{
function move(){
document.getElementById('tgt1').value =
document.getElementById('Allocation').value;
document.getElementById('Allocation').value="";
document.getElementById("Send").disabled=true;
}document.myform.action="Alloc_Insert.do";
}
else if(but==1)
{
document.myform.action="";
}
else if(but==2){ document.myform.action="WL_Verif.do";}
else if(but==3){ document.myform.action="Add_Query.do";}
document.myform.submit();
}
And the html is as below:
<input type="Submit" value="Allocate" id="Send" name="submit" onClick="invoke(0);move();"/><br/>
change the name of the button to something else than "submit"
To explain what happens:
When you assign the name-attribute "submit" to the button(or any other form-element), this element will be accessible via
document.myform.submit
but there is also the build-in method of a form: submit(), you also may access it by using
document.myform.submit
What happens now when you call document.myform.submit()
I'll write the code a little bit different, and you will see trouble:
document.myform['submit']()
Instead of accessing the built-in method, the code points first to the form-element, and then tries to execute the method. But a form-element is not a method, it all ends up in an error and the rest of the script(including the call of move() ) will not get executed.
It's the same with "reset", you never should use the name of a built-in property/method of the form-element as name for form-elements.
notice the 'move' function is not declared outside the 'invoke' function.
Then;
either wrap them in a self invoking function:
onclick="(function(){ invoke(0);move(); })();"
or attach event handlers (preferred usually)
div.attachEventListener('click', function () { ... }); // DOM 3
div.attachEvent('click', function () { ... }); // IE
Your functions are declared in a weird way. You're defining move inside of invoke, which I don't think you want. If you want to have two functions, put move outside of invoke, like this:
function move(){
document.getElementById('tgt1').value =
document.getElementById('Allocation').value;
document.getElementById('Allocation').value="";
document.getElementById("Send").disabled=true;
}
function invoke(but)
{
if(but==0)
{
move();
document.myform.action="Alloc_Insert.do";
}
else if(but==1)
{
document.myform.action="";
}
else if(but==2){ document.myform.action="WL_Verif.do";}
else if(but==3){ document.myform.action="Add_Query.do";}
document.myform.submit();
}
A note: it's generally not a good idea to use onClick in your HTML -- it's better to put that in your JavaScript.
I think the problem is the scope of the move() function. Try defining move outside of invoke.
function invoke (but) {
if(but==0) {
document.myform.action="Alloc_Insert.do";
// I don't know if you meant to call move() here or not
}
else if (but==2) { document.myform.action="WL_Verif.do"; }
else if (but==3) { document.myform.action="Add_Query.do"; }
document.myform.submit();
}
function move(){
document.getElementById('tgt1').value =
document.getElementById('Allocation').value;
document.getElementById('Allocation').value="";
document.getElementById("Send").disabled=true;
}
Also, properly formatting your code will do wonders to the legibility of it.
NOTE: Firefox seems to be quite happy to execute the onClick="invoke(0);move();" even if move is defined inside invoke. Chrome however won't execute move because it can't find it. So be sure to test your script in multiple browsers as well.
In and external JS file I have
$(document).ready(function() {
var example = function(){ alert("hello") }
});
and I want to call that function from my html, how would I do that?
<img src="..." ondblclick="example()" />
n.b. I'm aware of jquery dblclick() but curious about how to correctly do the above.
$(document).ready(function() {
window.example = function() {
alert("hello")
}
});
Or define it outside, if possible. It doesn't look like it has to be defined inside document ready at all.
The other solutions here will work, but structurally in your project, the best solution is to remove the event handling code from the HTML and hook up the event entirely via javascript (separate the HTML/JS). Since you already have jQuery in your project, this is very easy. To do that, all you need to do is to put some sort of identification on the image:
<img id="example" src="..." />
Then, in you can just hook up the event code in your ready() function like this
$(document).ready(function() {
$("#example").dblclick(function() {
alert("Hello");
});
});
This has the following advantages:
It creates no global variables - reducing the global namespace pollution.
It separates the HTML from the javascript which keeps all code governing the behavior in one compact spot and is usually a good thing
Using event listeners is a bit more scalable than using .ondblclick - allowing multiple different parts of code to use non-conflicting event handlers on the same object
Your function should be global (in fact, property of window object) if you want to access it from HTML. But best practice is to avoid global variables and functions, using namespace instead:
// let's publish our namespace to window object
if (!window.myNamespace){
// creating an empty global object
var myNamespace = {};
}
// and add our function to it
$(document).ready(function() {
myNamespace.example = function(){ alert("hello"); }
});
We can use it in HTML like this:
<img src="..." ondblclick="myNamespace.example()" />
The best option would be to simply define the function outside document.ready(). There is no reason defining the function within the $(document).ready() event is necessary, as if you call the function within the $(document).ready() function, the document is guarenteed to be ready.
However, you can also define the function on the global window object, like so:
$(document).ready(function() {
window.example = function(){ alert("hello") }
});
You can either move the function declaration outside of the DOM-ready handler:
function example(){ alert("hello") }
$(document).ready(function() {
// code
});
But the better solution is to keep JavaScript in your .js files and avoid the inline event handlers. Give your element an id and fetch it:
<img src="..." id="imgid" />
$(document).ready(function() {
document.getElementById("imgid").ondblclick = function(){ alert("hello") }
});
#Esailija has answered it correctly but if you want to keep it as it is then simply remove var and make it global.
var example;
$(document).ready(function() {
example = function() {
alert("hello")
}
});
If you do not put var the variable/function/object becomes global. Using var you were setting its context within document.ready function.
In trying to namespace my js/jquery code, I have come up against the following problem.
Basically, I used to write all my JS code in each html/php file, and I want to abstract that away to a single js file with namespaces.
So, in my html file I have:
<script type="text/javascript">
$(document).ready(productActions.init());
</script>
And in my js file I have:
var productActions = {
init: function() {
alert('initialsed');
$('#field_id').change(function() {
alert('ok!');
});
}
The productActions init function is definitely running, because I get the first alert (initialised). However, it seems that none of the jquery binding functions do anything at all. Stepping through the init function shows that the above change function is being registered, but actually changing the value in the field does absolutely nothing.
Am I missing something obvious here?
$(document).ready(productActions.init());
This code calls init() immediately and passes its return value to ready(...). (just like any other function call)
Instead, you can write
$(document).ready(productActions.init);
To pass the function itself. Howeverm this will call it with the wrong this; if you need this, write
$(document).ready(function() { productActions.init() });