I'm trying to change a value in a dropdown box and then trigger the event that happens when the value changes. The code is quite simple and looks like this:
zScalerEndPointList.on("change", function(){
// Change the value
$("select#phase1_type").val("string:ddns");
// Trigger the change
$("select#phase1_type").trigger("change");
})
The value is successfully changed, but the event is not triggered. If logging the object with jQuery I can see that the attached change event is null. However, if running the following command manually in the Javascript console window it works:
$("select#phase1_type").trigger("change");
Any ideas on what could be wrong? I do not own the application, this is a Javascript executed via TamperMonkey.
Grateful for any input.
/Patrik
I am not sureI got you but you can use watch for the dorpdown list or anything similar to this
$scope.$watch(function () { return self.filter; }, function (newValue, oldValue) {
if (newFilter != oldFilter) {
// call trigger
}
}, true);
Turns out this is a duplicate question. That I've asked before. A bit awkward. :)
Tampermonkey: Trigger event does not work for element
Solved it with the following function:
function triggerEvent(e, s){
"use strict";
var event = document.createEvent('HTMLEvents');
event.initEvent(e, true, true);
try {
document.querySelector(s).dispatchEvent(event);
} catch(err){
console.log("Unable to fire event " + e + " on selector " + s);
console.log(err);
}
}
Looks like both web applications is using some transpiled framework which makes life hard for me by removing and re-adding elements to the DOM. Hope this helps someone else too.
/Patrik
Related
I need to execute code from 3 different places on my website when an event gets triggered. I've added 3x listeners but for some reason only the first listener gets called.
Here's the code I'm testing at the moment: JSFiddle
window.addEventListener('tompina_event', function (e) {
document.write("triggered 1");
});
window.addEventListener('tompina_event', function (e) {
document.write("triggered 2");
});
window.addEventListener('tompina_event', function (e) {
document.write("triggered 3");
});
var evt = new CustomEvent('tompina_event');
window.dispatchEvent(evt);
Result:
triggered 1
This is the result I was hoping for:
triggered 1triggered 2triggered 3
It works, but the document.write destroys the original page and thus the execution of other code.
Please rewrite so the result is set in an other way like alert("triggered 1") or console.log("triggered 1").
The problem is with document.write(). Each call is overriding the strings from the previous call, and it appears that only one is firing. Change to console.log(), or document.body.innerHTML += "" and you will see them all firing.
The write() method is mostly used for testing: If it is used after an HTML document is fully loaded, it will delete all existing HTML.
I'm still in the beginning stages of my Angular 1.0 journey. I'm learning to like it, but I'm still scratching my head in a few places.
Lately, I've run into something while using $watch that's left me confounded. Take a look:
$scope.$watch('cookies', function() {
if ($cookies.getAll().redditSession) {
$scope.$emit('cookiesChanged')
// $scope.userWelcome = cookieService.decodeCookie($cookies.get('redditSession'))
}
})
$scope.$on('cookiesChanged', function() {
$scope.userWelcome = cookieService.decodeCookie($cookies.get('redditSession'))
})
This code works. If my cookies change, I emit an event thereby triggering the event listener, which changes the value of $scope.userWelcome to some value stored in the cookie. I see this change if I navigate to another route in my app.
However, I'm wondering why I had to use an event emitter here? Notice the line I commented out. I tried this first, but it doesn't change value of $scope.userWelcome, even if I move to another page in my app. I have to reload the page in order to see that I'm logged in.
What's going on here?
Try watching the cookie directly:
$scope.$watch(
function () {
return $cookies.get('redditSession');
},
function (newValue) {
if (newValue) {
$scope.userWelcome = cookieService.decodeCookie(newValue);
};
}
);
Your mistake is that you try to get the new value with the standard method. The way you can actually get the new value is adding it to the parameters of the function. Here it goes:
$scope.$watch('cookies', function(newValue, oldValue) {
if (newValue.getAll().redditSession) {
$scope.userWelcome = cookieService.decodeCookie(newValue.get('redditSession'))
}
// also try this
console.log(oldvalue === $cookies);
});
Cheers!
I have a script with the following (only showing the applicable lines)
var setUploadDoneIndicator = function(form)
{
if ($(form).find('[id$=_upload_done_indicator]').is(':checked') == false)
{
console.log("Setting indicator");
$(form).find('[id$=_upload_done_indicator]').trigger('click');
}
}
var unsetUploadDoneIndicator = function(form)
{
if ($(form).find('[id$=_upload_done_indicator]').is(':checked') == true)
{
console.log("UnSetting indicator");
$(form).find('[id$=_upload_done_indicator]').trigger('click');
}
}
$('[id$=_upload_form]').each(function (event)
{
current_form = this;
$(this).fileupload(
{
done: function (e, data)
{
setUploadDoneIndicator(current_form);
}
});
}
This ticks a checkbox correctly, the idea is to listen on the checked state of the checkbox on another JS File. If I call unsetUploadDoneIndicator() right after setUploadDoneIndicator() in this script, it unticks the tickbox.
Then in another JS file I have
$('#pricing_ab_upload_done_indicator').change(function()
{
if ($(this).is(':checked'))
{
console.log("got checked");
unsetUploadDoneIndicator($('#pricing_ab_upload_form'));
}
});
Which calls the function in the first script, but does not untick the tickbox. I am unsure whether the pointer is passed over correctly, when printing out the received object in unsetUploadDoneIndicator() it does print out a JQuery object which seems correct, the
if ($(form).find('[id$=_upload_done_indicator]').is(':checked')
returns true, but the trigger does not happen, so i'm not sure if the element is actually found.
If I change the second script with the following, the trigger to uncheck the box does not happen either
$('#pricing_ab_upload_done_indicator').change(function()
{
if ($(this).is(':checked'))
{
console.log("got checked");
$('#pricing_ab_upload_done_indicator').trigger('click');
}
});
Why would the trigger not happen?
It's easier to just remove your functions and use the following:
$('[id$=_upload_form]').each(function (event) {
current_form = this;
$(this).fileupload( {
done: function (e, data) {
var checkbox = $(current_form).find('[id$=_upload_done_indicator]');
// Set the opposite value
checkbox.prop("checked", !checkbox.prop("checked"));
}
});
}
Avoid binding multiple events on the same action. I see you have a .change event on the checkbox as well, which will result in the "click" event triggering twice. This will make it look like nothing happened.
On a sidenote, if you are using the same selector often (like $(current_form).find('[id$=_upload_done_indicator]') in your code example), it's better to cache it in a variable to increase performance. It's also easier to work with to write a short variable name instead of repeating the entire selector.
Following #Dark Ashelin's advice, I added a custom event. This seems like a much simpler and more logical way of implementing this type of functionality.
In the first script when the upload is done I have
$(current_form).trigger('event_upload_completed');
In the second script I have
$('#pricing_ab_upload_form').on('event_upload_completed', function()
{
console.log("Upload completed");
});
This way does not require a callback to the first script from the second script to reset the state of the checkbox (it does not require a dummy html element at all)
I tested this in the latest Chrome and FireFox and in IE11. If this method has compatibility issues with older IE's please comment on this answer
How can I return a parent function from a child function on click? Here's an example code:
function returnFunction() {
var output = false;
$('a').click(function() {
output = true;
});
return output;
}
var result = returnFunction();
The result will always be false since the click hasn't happened at the time the code is being run. How could I make this work though?
My intention is to call pop-up dialogs, and I'd like to have all the logic inside one function that can easily be loaded - including the click events of a Confirm dialog box.
Elsewhere in scripts I'd be calling it this way for example:
// Menu click triggers the dialog
$('a').click(function(e) {
// The function displays the dialog and returns the click events of the dialog
var result = returnFunction();
// If result was false, we'll prevent the menu access, for example
if (!result) {
e.preventDefault();
}
});
I'm aware of the jQuery UI dialog plugin. But I'd like to achieve this without it for now.
Thanks.
An over-simplification of it is:
Everything stops (including scrolling and clicking on hyperlinks) while executing javascript. This means you cannot "pause" the script until someone clicks on a link.
The typical way of solving this is a callback function:
function my_callback(some, arguments) {
// you can do whatever in here: an ajax load, set a global variable, change some of the page, ...
console.log(some, arguments);
alert(some + " " + arguments);
}
function returnFunction(callback, param) {
var output = false;
$('a').click(function() {
callback(param, "world");
});
}
returnFunction(my_callback, "hello");
demo at http://jsfiddle.net/UnBj5/
EDIT:
I did mention global variables because they are an option, but they are typically bad style. Try to use other means if possible.
If you want more help with it, provide more details of what you are trying to do.
Try using parameters instead. Send a parameter to a function that shows your alert boxes, show a different pop-up alert depending on the parameter, what you are trying to do won't work because its basically a chicken-egg problem.
I am a rookie in JS, have a problem understanding JQUERY semantics.
I have a function written for checking the content of a cell.
Problem: the function just starts when the cell loses focus, if I click Submit, the error shows first, then it will run the function.
I want the function to run even when I am inside the cell. How to do it?
Initiated by this:
$(".user_id").blur(function(){ validateUserId($('.user_id')); });
The function:
function validateUserId(reference) {
if ( 5 == $(reference).val().length ) {
$.get('index.php?user=' + $(reference).val(), function(data) {
if ( "error" == data ) {
$(reference).parent().parent().addClass('error');
alert('error');
} else {
$(reference).parent().parent().removeClass('error');
$(reference).addClass('valid');
$(reference).parent().parent().addClass('success');
}
});
} else {
alert('short');
$(reference).parent().parent().addClass('error');
}
}
$(".user_id").on('keyup', function(){
validateUserId($(this));
});
i would use the keyup event.
So everytime somebody types a key in your input cell, the function will be executed.
$(".user_id").on("keyup", function(){ validateUserId($(this)); });
I changed the $(".user_id"), you take the value from ,to $(this). Since you want the value of the field you did the keyup event on. (And not an other field, if there would be 2 fields with the same .user_id class.)
Try to bind function on focus event
$("input[submit]").click(function(e){
e.preventDefault();
var valid = validateUserId($('.user_id')); // maybe the function could return a boolean value too instead of just adding classes to the HTML part
if (valid) {
$("#your_form_id").submit(); // only if the input is valid, submit it
}
});
sidenote on your problem: if you click the submit button it will first trigger the submit action which may give you an error and then execute the blur() block of code
Here is a working demo http://jsfiddle.net/pomeh/GwswM/. I've rewritten a little the code to:
cache DOM selections into variables,
use jQuery methods chaining,
improve if conditions with tripe equal signs,
separated AJAX calls and application logic,
cache identical AJAX calls,
use jQuery deferred to hide the asynchronous aspect of the verification (linked to AJAX)
Hope that'll help :)