How can I pass args to the event handler function? This runs the function on page load which is not the desired effect. I need this routine validateText to run against several different textbox, dropdown combinations. Can I reuse validateText instead of creating one per text/dropdown combination??
//add blur event handler to the textbox with jQuery when the page is finished loading
$(document).ready(function() {
$("#myTextbox").blur(validateText($("#myTextbox"), $("#Select1")));
})
function validateText(textbox, dropdown) {
var message = $("#message");
var isValid = false;
//get the value the user type in
var textboxValue = $(textbox).val();
//get the options from the lookup
var options = $("option", dropdown);
//loop through the options and compare it to "value"
options.each(function() {
var optValue = $(this).val();
if (optValue === textboxValue) {
isValid = true;
}
});
if (!isValid)
message.text(textboxValue + " is not a valid value from the list.");
else
message.text(textboxValue + " is perfectly valid.");
}
Use binding to pass extra parameters to an event listener:
http://docs.jquery.com/Events/bind
$(document).ready(function() {
$("#myTextbox").bind("blur", [ $("#myTextBox"), $("#Select1")], validateText);
})
Then access the data from event.data:
function validateText(event) {
textBox = event.data[0];
dropdown = event.data[1];
}
The reason it calls at load is because handing over a function name with arguments actively calls it. You can effectively mimic what you're looking for by wrapping the call to validateText in an anonymous function like so.
$(document).ready(function() {
$("#myTextbox").blur(function(){
// Since in your original example you used $("#myTextbox") as an arg, this mimics it
validateText($(this), $("#Select1"));
});
});
The anonymous function, since it's using the 'this' keyword, should scale a little better with your initial selector if you change it from #myTextbox to textarea or whatever. =)
Related
I've been working on this code for a while. I have a HTML, JS and a Code.js page.
On changing of the value in a Dropdown list on my HTML form, the item in the Dropdown is passed to the Code.js to have the result returned, however, I keep having NULL as my result. -arr is the result.
Another issue, is that I can see in the script logs that getRowData() is being executed twice, not sure why, but this may be overwriting our array.
HTML
JS
//$('#searchDropdown').one('change', function(){
//$("#searchDropdown").change(function(){
//$('#searchDropdown').on('keyup propertychange change', function(){
//$('#searchDropdown').on('input', function(){
//$('#searchDropdown').one('submit', function(){
$('#searchDropdown').one('change', function(){
var selatr = $('#input1').val();
google.script.run.withSuccessHandler(poperr).getRowData(selatr);
});
function poperr(arr){
alert(arr +" ! ");
}
Code.GS
function getRowData(selatr){
//Vlookup a GoogleSheet and return the resulting row
sheet_data.getRange(2,16).setValue(selatr); //set for vlookup
var x = sheet_data.getRange(3,16).getValues();
var arr= [];
arr.push({
id : selatr
name : sheet_data.getRange(x,2).getValues()
})
return arr;
}
It might be because you have multiple event handlers in your code and your getRowData function is being called twice.
Try e.stopImmediatePropagation(); This stops the rest of the event handlers from being executed.
$('#searchDropdown').one('change', function(e){
e.stopImmediatePropagation();
var selatr = $('#input1').val();
google.script.run.withSuccessHandler(poperr).getRowData(selatr);
});
I couldn't find any solutions for my problem yet. Maybe I used wrong keywords.
I'm trying to update the value of an input field onchange after a .load() action has been performed.
Here is my script:
$(document).on("change",".myInput",function() {
var value = $(this).val();
$('#actionDiv').load("someAction.php?value="+value, function() {
$(this).val('OK');
});
});
So, after someAction.php has been loaded into #actionDiv successfully, I'd like to change the value of that input field, that has been changed.
I have several input fileds, which take this kind of action...
It seems "$(this)" is unknown in the function after load() has been completed.
Can anyone please help?
Thanks
You need to store a reference to the element, or use an arrow method which doesn't change the value of this
$(document).on("change",".myInput",function() {
var that = this;
var value = $(that).val();
$('#actionDiv').load("someAction.php?value="+value, function() {
$(that).val('OK');
});
});
OR
$(document).on("change",".myInput",function(e) {
var value = $(e.target).val();
$('#actionDiv').load("someAction.php?value="+value, function() {
$(e.target).val('OK');
});
});
OR
$(document).on("change",".myInput",function() {
var value = $(this).val();
$('#actionDiv').load("someAction.php?value="+value, () =>{
$(this).val('OK');
});
});
So I'm fairly novice with jquery and js, so I apologise if this is a stupid error but after researching I can't figure it out.
So I have a list of data loaded initially in a template, one part of which is a dropdown box that lets you filter the data. My issue is that the filtering only works once? As in, the .change function inside $(document).ready() only fires the once.
There are two ways to reload the data, either click the logo and reload it all, or use the search bar. Doing either of these at any time also means the .change function never fires again. Not until you refresh the page.
var list_template, article_template, modal_template;
var current_article = list.heroes[0];
function showTemplate(template, data)
{
var html = template(data);
$("#content").html(html);
}
$(document).ready(function()
{
var source = $("#list-template").html();
list_template = Handlebars.compile(source);
source = $("#article-template").html();
article_template = Handlebars.compile(source);
source = $("#modal-template").html();
modal_template = Handlebars.compile(source);
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
$("#classFilter").change(function()
{
console.log("WOW!");
var classToFilter = this.value;
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.heroClass.search(classToFilter) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
$("#searchbox").keypress(function (e)
{
if(e.which == 13)
{
var rawSearchText = $('#searchbox').val();
var search_text = rawSearchText.toLowerCase();
var filteredData =
{
heroes: list.heroes.filter(function(d)
{
if (d.name.search(search_text) > -1)
{
return true;
}
return false;
})
};
console.log(filteredData);
showTemplate(list_template,filteredData);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = filteredData.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
}
});
$("#logo").click(function()
{
showTemplate(list_template,list);
$(".articleButton").click(function()
{
var index = $(this).data("id");
current_article = list.heroes[index];
showTemplate(article_template,current_article);
$('.poseThumb').click(displayModal);
});
});
//$("#logo").click();
});
function displayModal(event)
{
var imageNumber = $(this).data("id");
console.log(imageNumber);
var html = modal_template(current_article.article[0].vicPose[imageNumber]);
$('#modal-container').html(html);
$("#imageModal").modal('show');
}
I should note two things: first, that the search bar works perfectly, and the anonymous function inside both of them is nearly identical, and like I said, the filtering works perfectly if you try it after the initial load. The second is that the same problem occurs replacing .change(anonymous function) with .on("change",anonymous function)
Any help or advice would be greatly appreciated. Thanks.
I agree with Fernando Urban's answer, but it doesn't actually explain what's going on.
You've created a handler attached to an HTML element (id="classFilter") which causes part of the HTML to be rewritten. I suspect that the handler overwrites the HTML which contains the element with the handler on it. So after this the user is clicking on a new HTML element, which looks like the old one but doesn't have a handler.
There are two ways round this. You could add code inside the handler which adds the handler to the new element which has just been created. In this case, that would mean making the handler a named function which refers to itself. Or (the easier way) you could do what Fernando did. If you do this, the event handler is attached to the body, but it only responds to clicks on the #classFilter element inside the body. In other words, when the user clicks anywhere on the body, jQuery checks whether the click happened on a body #classFilter element. This way, it doesn't matter whether the #classFilter existed when the handler was set. See "Direct and delegated events" in jQuery docs for .on method.
Try to use some reference like 'body' in the event listeners inside your DOM like:
$('body').on('click','.articleButton', function() {
//Do your stuff...
})
$('body').on('click','#classFilter', function() {
//Do your stuff...
})
$('body').on('keypress','#searchbox', function() {
//Do your stuff...
})
$('body').on('click','#logo', function() {
//Do your stuff...
})
This will work that you can fire it more than once.
I have a single shared jQuery function that checks a RadioButton selection: if 1 is selected, it hides a span, otherwise it shows it.
This shared function is called both on startup and on Change, because on startup, it needs to do the same thing. The startup works, but the onChange reference does NOT work:
JS_OBJ = {
toggleTier : function() {
if ($('input[name="tier"]:checked').val() == 'Y_YES')
{
$('#tierSpan').hide();
}
else
{
$('#tierSpan').show();
}
},
// this is called from document.onReady - it comes here, OK
onReady : function() {
// on startup, toggle Tier - works OK
this.toggleTier();
// Also link the radio button Change to this shared function
$('input[name="tier"]:radio').change(function () {
alert('About to enter toggle...');
// NEVER COMES HERE - Object doesn't support this property or method
this.toggleTier();
});
}
};
the this is changing value as it is passing thru the different zones. when it is first instantiated, it has a good value, but the radiobutton:change has a different this
I was able to change it get it to work:
$('input[name="tier"]:radio').change(function () {
alert('About to enter toggle...');
self; //closure
toggleTier();
});
see this: What underlies this JavaScript idiom: var self = this?
Inside the change event, this does not refer to the current JS_OBJ, it refers to the current event target in stead. You want to explicitly save your reference to this, so you can use it inside the event.
Example:
onReady : function() {
var me = this;
me.toggleTier();
// Also link the radio button Change to this shared function
$('input[name="tier"]:radio').change(function () {
me.toggleTier();
});
}
I have a non-jquery script with an addEventListener on a buttonclick. This works fine the first run but I want it to change "sendingurl" to some other value after the first click. (the succesfull insert of form becomes an update form). However, even though sendingurl fills with the new id value, it doesnt change after the event is fired again. Instead by the second click it fires the newly created event tohether with the old one with the old value.
The resulting values in console.log:
1st click: event "click" is fired with url: input.php
2nd click:
event "click" is fired with url: input.php
event "click" is fired with url: update.php?io=items&id=693
So I want to get rid of the input being triggered after the first click. Does someone know how to solve this?
var itemid = getHash();
ini(prepare); // using window.onload to execute
function prepare() {
if (itemid) {
// update
var sendingurl = 'update.php?io=items&id=' + itemid;
} else {
// input
var sendingurl = 'input.php';
}
// submitevent
æ($("submitBtn"), 'click', function() {
console.log("event \"click\" is fired with url: " + sendingurl);
var json = new FormData(document.forms[0]);
ajax(sendingurl, json, submittedInput);
});
}
// callback function after ajax did his magic
function submittedInput(response) {
if (response) {
if (!itemid) {
itemid = response;
prepare();
}
} else {
$("status").innerHTML = "something went wrong with the input";
}
}
// function to add events without the use of jquery or prototype
function æ(el, evType, fn, useCapture) {
if (el.addEventListener) {
el.removeEventListener(evType, fn, useCapture);
el.addEventListener(evType, fn, useCapture);
return true;
} else if (el.attachEvent) {
el.detachEvent('on' + evType, fn);
var r = el.attachEvent('on' + evType, fn);
return r;
} else {
el['on' + evType] = fn;
}
}
The first time through, there is no event handler to remove and your anonymous function is added as an event handler. The anonymous function creates as closure, so the value of sendingurl is now "constant" no matter how the external sendingurl changes. That is why you are getting the old value.
The second time through, the event handler function being passed to removeEventListener is not yet tied to an event because the second anonymous function is not the same function as the anonymous function on the first pass. So no event handler is removed. You then add a second event with the new anonymous function with the revised value of sendingurl. That is why you are seeing both functions fire.
Convert your anonymous function to a normal function and use the normal function name instead.