Javascript - $(this).on - javascript

Why it can retrieve the "modelValue" when inputText changed ?
Who can describe the flow of this script ?
Thanks
//js預載入
$(document).ready(function() {
console.log("ready!");
var iepValues = $('body').find('[model-value]');
$.each(iepValues, function() {
var modelValue = $(this).attr('model-value');
console.log("display");
//Why it can retrive the "modelValue" when inputText chagned ?
$(this).on('change', function() {
console.log("modelValue:" + modelValue);
});
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<body>
TEST1:
<input type="text" id="TxtTest1" model-value="A">TEST2:
<input type="text" id="TxtTest2" model-value="B">
</body>

Why it can retrieve the "modelValue" when inputText changed ?
Because the function hooked up with $(this).on('change', function() { ... }); is called when the value of the input changes, and that function closes over (has access to) the modelValue variable in context where it was created.
Who can describe the flow of this script ?
It calls jQuery's ready function, passing in a function to call when the DOM is ready. All of the rest of the code is in that callback.
When the DOM is ready, jQuery calls the callback.
The code logs "ready!" and the finds all elements inside body that have a model-value attribute. [Side Note: $('body').find('[model-value]') can more concisely and efficiently be written $('body [model-value]').]
The code loops through all of those elements using $.each, calling a callback function for each of them.
Inside that callback, the code grabs the value of the model-value attribute and stores it in a variable. There will be a different variable for each of the elements, each variable contained by the context of the call to the callback from $.each.
Code in each of those callbacks hooks up a handler for the change event of that element.
The handler responds to the change event by logging the value of the modelValue variable.
Recommended reading:
The jQuery API
How do JavaScript closures work?
JavaScript closure inside loops – simple practical example
If the element's model-value attribute is going to change, that code will log the value it had when the DOM was ready, not the value it has when the value of the input changes. That would seem to be the point of the code.
If the model-value attribute doesn't change, then the code is unnecessarily complicated, and could just be:
$(document).ready(function() {
console.log("ready!");
$('body [model-value]').on('change', function() {
console.log("modelValue:" + $(this).attr('model-value'));
});
});
Or even:
console.log("ready!");
$('body [model-value]').on('change', function() {
console.log("modelValue:" + $(this).attr('model-value'));
});
If you move the script tag to the bottom of the HTML, just before the closing </body> tag.
But again, that's if the model-value attribute doesn't change, or if you want to see the changed value instead of the original value. The original code will show you the original, not changed, value of the attribute.

Related

jQuery bind event on element fails

We are using jQuery 2.1.4 and have written out own JavaScript class that should take care of the event. It is a very simple "application". All it does is taking care of submitting a form. Before that, it processes the data.
Our initial method that we call on rendering the page:
OWebForm.prototype.init = function(){
console.log("init Method called");
...
$("#submit_message").on("click", this._submit);
console.log($("#submit_message"));
...
}
OWebForm.prototype._submit = function(e){
e.preventDefault();
console.log("_submit Method called");
...
}
Once the button "#submit_message" is clicked, it is supposed to call the _submit method of the OWebForm class. When looking at the element within the console I can see that it is not bound to anything, when the page is loaded. Hence the code is not executed once the button is clicked.
In the HTML I have the following code:
<script type="text/Javascript">
var _oWebForm = new OWebForm("0bcfwqx23xv02dfaqfujdqyafziic4b07uxkkg1y6lkof7x0px0vjm2tpaik2l2rmlrhnjya0bvctnpq26dqcom1ij5zpibodke3rs1z4f2syllthtj0kpl3p4vrw0vw");
_oWebForm.init();
</script>
From the documentation I understood, that the function has to exist before it is bound to an element event. Is this not the case when working with objects? How would I fix this?
Your script is executed before the DOM is loaded so the element doesn't exist yet, and the jQuery selector doesn't match anything, so no elements get a click handler bound to them. You need to call the init() method with in $(document).ready().
A page can't be manipulated safely until the document is "ready." jQuery detects this state of readiness for you. Code included inside $( document ).ready() will only run once the page Document Object Model (DOM) is ready for JavaScript code to execute.
$(document).ready(function() {
var _oWebForm = new OWebForm("0bcfwqx23xv02dfaqfujdqyafziic4b07uxkkg1y6lkof7x0px0vjm2tpaik2l2rmlrhnjya0bvctnpq26dqcom1ij5zpibodke3rs1z4f2syllthtj0kpl3p4vrw0vw");
_oWebForm.init();
});
This works for me:
var OWebForm = function(a){
};
OWebForm.prototype.init = function() {
alert("init Method called");
$("#submit_message").on("click", this._submit);
}
OWebForm.prototype._submit = function(e){
e.preventDefault();
alert("_submit Method called");
}
$(function() {
var _oWebForm = new OWebForm("0bcfwqx23xv02dfaqfujdqyafziic4b07uxkkg1y6lkof7x0px0vjm2tpaik2l2rmlrhnjya0bvctnpq26dqcom1ij5zpibodke3rs1z4f2syllthtj0kpl3p4vrw0vw");
_oWebForm.init();
});
<script src="http://code.jquery.com/jquery-1.11.3.js"></script>
<form id="myFrm">
<input type="text">
<input id="submit_message" type="submit" value="Click me To test">
</form>
You need to substitute:
$("#submit_message").on("click", this._submit);
with:
$(document).on("click", "#submit_message", this._submit);
If the submit_message is not already loaded!

Call onclick attribute programatically and talk to the event parameter

I have read the other post relating to this matter. Unfortunately it has not resolved my problem. I am happy to use jQuery, so I am looking for the cleanest solution.
I have radio buttons defined as follow:
a = 5;
input.value = "myButton";
input.onclick = (function (a) {
return function (e) {
changeSelectedRadio(e.srcElement, a);
};
})(a);
I need to be able to execute this when user click on the radio button (this works fine), and programatically.
I have tried:
$("input[type='radio'][value='myButton']").triggerHandler("click");
$("input[type='radio'][value='myButton']").click();
Both produce the same result: e (the event parameter) does not exist.
$("input[type='radio'][value='myButton']").onclick();
Does not work
Changing the input.onclick to input.click also did not work. When the use click, the function does not get triggered.
Thanks
If you're using jquery already, might as well build the inputs that way:
var input = $('<input value="something">').click(function(){
var elem = $(this); // the element clicked, as a jquery obj
alert(elem.attr('id');
});
$('body').append(input);
$('input').trigger('click');
Adjust the selectors as needed, and you'll need to actually append the elements to the DOM, but it'll work.
try this:
$("input[type='radio'][value='myButton']").bind( "click", function() {
alert( "clicked" );
});
What is passed to the function is a jQuery event, not a native event. You can use the target element to get at the source that was clicked on or use this to reference the properties of the object directly. See fiddle at http://jsfiddle.net/YQh3Q/
<p><input id="foo1" name="foo" type="radio" value="0" checked="checked"> Foo1</p>
<p><input id="foo2" name="foo" type="radio" value="1"> Foo2</p>
(function ($) {
var input = document.getElementById("foo2");
var a = 5;
input.value = "myButton";
input.onclick = (function (a) {
return function (e) {
alert(e.target + '|' + this.id);
};
})(a);
$("input[type='radio'][value='myButton']").each(function() {
$(this).trigger("click");
});
})(jQuery);
Alternatively (and probably better) you can use a pure jQuery solution
$(function() {
var a = 5;
$('input#foo2').on('click', function() {
changeSelectedRadio(this, a);
})
.val('myButton');
$("input[type='radio'][value='myButton']").trigger('click');
});
Its best to use addEventListener() you can add all types of events. example: "click", "mousemove", "mouseover", "mouseout", "resize" and many more. the false at the end is to stop the event from traversing up the dom. If you want parent dom objects to also receive the event just change it to true. also this example requires no javascript libraries. This is just plain old javascript and will work in every browser with nothing extra needed.
Also addEventListener() is better than onClick() as you can add an unlimited number of event listeners to a dom element. If you have an onClick() on an element and then set another onClick() on the same element you have overwritten the first onClick(). Using addEventListener() if i want multiple click events to trigger when i click on an element i can do it with no problem.
If you want data about the element that is triggering the event you can pass the event to the function. You will see in my example function(e) e is the event and you can use e or this to target the element that is being triggered. Using e or this i can also get more data about the triggered event. for example if the event was a mousemove or mouseclick i can get the x and y position of the mouse at the time of the event.
<!DOCTYPE html>
<html>
<head>
<title>exampe</title>
</head>
<body>
<a id="test" href="">test</a>
<script>
document.getElementById("test").addEventListener("click",function(e){
alert('hello world');
alert('my element '+e);
alert('my element '+this);
},false);
</script>
</body>
</html>
if you want to have addEventListener call a function just change the 2nd value to the function name like this.
document.getElementById("test").addEventListener("click",f1,false);
this will execute the function
function f1(){ ... }
When you want to remove an event listener just call target.removeEventListener(type, listener[, useCapture]). Very simple and easy to manage.

Passing 'this' as parameter in JavaScript

I have the following code:
HTML:
<label id="copyAddress" class="copyAddress" onclick="CopyAddress(this);">
Copy Address
</label>
JS:
function CopyAddress(copyAddressLink) {
PopulateTarget(copyAddressLink);
}
function PopulateTarget(link) {
var targetGroup = $(link).closest('someClass');
}
In PopulateTarget function 'link' variable is undefined, while in CopyAddress it has values as is should.
What can cause this problem? Is there some restriction for passing parameters in Java Script? How this should behave? If you need more code to post please tell me.
Since you are anyhow using jQuery, why are you using obtrusive Javascript?
Use this instead:
HTML:
<label id="copyAddress" class="copyAddress">Copy Address</label>
Javascript:
$(document).ready(function(){
$('#copyAddress').click(function(){
var targetGroup = $(this).closest('.someClass');
});
});
You're missing a dot on "someClass", it should be ".someClass".
Maybe your code will work after you fix that. However: since you're using jQuery (it seems you are), you should attach the click handler the jQuery way, instead of inline on the HTML. This means:
$(document).ready(function(){
$('#copyAddress').click(CopyAddress);
})
function CopyAddress() {
PopulateTarget(this);
}
function PopulateTarget(link) {
var targetGroup = $(link).closest('someClass');
}
You should not intermix your HTML and JS. You should instead attach your JS handlers programmatically in your JS code:
<!-- note: no onclick in this html -->
<label id="copyAddress" class="copyAddress">Copy Address</label>
// Wait until the page is loaded before starting to look for elements
$(function(){
// Assuming jQuery 1.7
$('#copyAddress').on('click',copyAddress);
// …alternatively, for older jQuery
$('#copyAddress').click(copyAddress);
function copyAddress(evt){
// The 'target' property of the event object passed in is the object
// upon which the event was first triggered.
PopulateTarget(evt.target);
}
});
In the case of the above, you could just use this instead of evt.target, since you bound the event directly on that object. However, this becomes more powerful if you have a variety of items on the page that perform this function. You can attach the event handler once to some parent object, and then ask—during the callback—which element was clicked on. That would look like:
// Watch for any element with a copyAddress class to be clicked on,
// even if they are added after this code has run
$(document.body).on('click','.copyAddress',function(evt){
var target = evt.target;
console.log("You clicked on",target);
});
As it seems you are using jQuery:
You can use jQuery.proxy to bind this to a specific value. It is used like this:
jQuery.proxy(function () { console.log(this); }, this);

Workaround for passing parameter to jQuery ready()

I have some code called on jQuery document.ready() which is used in multiple HTML files. Now the difference is each of these HTMLs uses a different div id.
I know one option is to just check for hardcode div ids inside $(document).ready() . But I wanted to write a generic code which would take the div Ids based on the currrent/calling HTML page?
So is there any way or workaround for passing parameter to jQuery ready() ?
$(document).ready() just wants a function as an argument so you can write a function that takes your ID as an argument and returns a function for $(document).ready(). For example, instead of this:
$(document).ready(function() {
$('#some_id').click(/*...*/);
});
you could do this:
function make_ready(id) {
return function() {
$('#' + id).click(/*...*/);
};
}
$(document).ready(make_ready('some_id'));
Then you could put your make_ready in some common location and use it to build the functions for your $(document).ready() calls.
document ready just takes in an handler function as a parameter.
You can still define a generic code in you document ready function, by storing the current div id for each html.
<input type="hidden" id="current_div" value="div1" />
$(document).ready(function() {
var div_id = $('#current_div').val();
// generic code
});

Passing argument to JS function from link onclick

I have a link that looks like this:
<a id="mylink" onclick="deleteHike( 3 );" href="javascript:void(0);">Yes</a>
It is able to call this JavaScript:
window.onload = function()
{
//Get a reference to the link on the page
// with an id of "mylink"
var a = document.getElementById("mylink");
//Set code to run when the link is clicked
// by assigning a function to "onclick"
a.onclick = function( hike_id )
{
// Somecode her
// But when I try to use the hike_id it displays as [object MouseEvent]
}
}
But the value that comes in is [object MouseEvent], not the number that I was expecting. Any idea why this happens and how to fix this? :)
Thanks!
You are trying to assign the function to your link in two different and conflicting ways.
Using the eval-ed function string, onclick = "function(value)", works but is deprecated.
The other way of binding the click handler in the onload event works too, but if you want a particular value to be passed, you'll have to change your script a bit because the value as given in the initial onclick is completely lost when you set the onclick to a new function.
To make your current method work, you don't need an onload handler at all. You just need this:
function deleteHike(hike_id) {
// Some code here
}
To do it the second way, which I recommend, it would look like this:
<a id="mylink" href="javascript:void(0);">Yes</a>
with this script:
function deleteHike(e, hike_id) {
// Some code here
// e refers to the event object which you can do nifty things with like
// - learn the actual clicked element if it was a parent or child of the `this` element
// - stop the event from bubbling up to parent items
// - stop the event from being captured by child items
// (I may have these last two switched)
}
function getCall(fn, param) {
return function(e) {
e = e || window.event;
e.preventDefault(); // this might let you use real URLs instead of void(0)
fn(e, param);
};
}
window.onload = function() {
var a = document.getElementById("mylink");
a.onclick = getCall(deleteHike, 3);
};
The parameter of a DOM event function is the event object (in Firefox and other standards-compliant browsers). It is nothing in IE (thus the need to also grab window.event). I added a little helper function for you that creates a closure around your parameter value. You could do that each time yourself but it would be a pain. The important part is that getCall is a function that returns a function, and it is this returned function that gets called when you click on the element.
Finally, I recommend strongly that instead of all this, you use a library such as jQuery because it solves all sorts of problems for you and you don't have to know crazy JavaScript that takes much expertise to get just right, problems such as:
Having multiple handlers for a single event
Running JavaScript as soon as possible before the onload event fires with the simulated event ready. For example, maybe an image is still downloading but you want to put the focus on a control before the user tries to use the page, you can't do that with onload and it is a really hard problem to solve cross-browser.
Dealing with how the event object is being passed
Figuring out all the different ways that browsers handle things like event propagation and getting the clicked item and so on.
Note: in your click handler you can just use the this event which will have the clicked element in it. This could be really powerful for you, because instead of having to encode which item it was in the JavaScript for each element's onclick event, you can simply bind the same handler to all your items and get its value from the element. This is better because it lets you encode the information about the element only in the element, rather than in the element and the JavaScript.
You should just be able to declare the function like this (no need to assign on window.onload):
function deleteHike(hike_id)
{
// Somecode her
// But when I try to use the hike_id it displays as [object MouseEvent]
}
The first parameter in javascript event is the event itself. If you need a reference back to the "a" tag you could use the this variable because the scope is now the "a" tag.
Here's my new favorite way to solve this problem. I like this approach for its clarity and brevity.
Use this HTML:
<a onclick="deleteHike(event);" hike_id=1>Yes 1</a><br/>
<a onclick="deleteHike(event);" hike_id=2>Yes 2</a><br/>
<a onclick="deleteHike(event);" hike_id=3>Yes 3</a><br/>
With this JavaScript:
function deleteHike(event) {
var element = event.target;
var hike_id = element.getAttribute("hike_id");
// do what you will with hike_id
if (confirm("Delete hike " + hike_id + "?")) {
// do the delete
console.log("item " + hike_id + " deleted");
} else {
// don't do the delete
console.log("user canceled");
}
return;
}
This code works because event is defined in the JavaScript environment when the onclick handler is called.
For a more complete discussion (including why you might want to use "data-hike_id" instead of "hike_id" as the element attribute), see: How to store arbitrary data for some HTML tags.
These are alternate forms of the HTML which have the same effect:
<a onclick="deleteHike(event);" hike_id=4 href="javascript:void(0);">Yes 4</a><br/>
<button onclick="deleteHike(event);" hike_id=5>Yes 5</button><br/>
<span onclick="deleteHike(event);" hike_id=6>Yes 6</span><br/>
When you assign a function to an event on a DOM element like this, the browser will automatically pass the event object (in this case MouseEvent as it's an onclick event) as the first argument.
Try it like this,
a.onclick = function(e, hike_id) { }

Categories

Resources