I've created some code for a custom entity involving dynamically displayed questions and the ability to answer them. I'm working on being able to display previously answered questions, along with the ability to update answers. To do so, I have certain functions fire onLoad of my custom entity form, and another fire onSave.
My trouble is that my onLoad code runs every time a save happens, effectively erasing the output of the onSave code. I only want my onLoad code to run the first time the form is loaded. Otherwise, the code I want to fire onSave should handle everything else.
One way I tried to solve this was using Xrm.Page.ui.getFormType(); This returns a value of 1 or 2, with 1 corresponding to the record being created, and 2 corresponding to the record being updated. This worked for one scenario -- I didn't want my onLoad code to run when a fresh record for the custom entity was being created, and getFormType() solved this. BUT when I saved the record, the return value changed, and caused my onLoad code to run OnSave, which messed things up.
Any ideas on how I would go about solving this? I can forsee something like getFormType() being useful, but I'm at a bit of a loss on how to go about things. Thanks!
Add an onChange event handler to the modifiedon attribute, this value would only ever change after a record is saved, you can have a global parameter and set its value and use its value to stop the onLoad from re-firing again.
var canRunOnLoadCode = true;
//form onLoad function
function onLoad() {
if(!canRunOnLoadCode) return;
//on load code below
}
//register the below function on change of modified on
function afterOnSave(){
canRunOnLoadCode = false;
}
Related
I'm not a javascript/jquery coder, and not sure if what I'm trying to do is possible.
I have a html/php/ajax form that is updated an sql database as the user fills it out. As they fill the form, there is a progress bar ran by javascript/jquery that updates as the user types in the input. The start of the function looks like this:
$("#update input").keyup(function() {
This works great. My problem is when the page is reloaded. My code is pulling sql data from the database to fill the value of every input on the page that has a value so that a user can come back and completely the form later. When the user reloads the page, the only way for the script to activate is if the user types in an input field.
I thought I would fix the issue by changing the my initial javascript/jquery function with $(document).ready(function() . This caused the script to only run when the page was loaded and not when the form was being filled out. I need both the script to run on page ready, and when a user is typing in the input filled. Is there a way I can run both $(document).ready(function() AND $("#update input").keyup(function() { simultaneously? Or is there a better why to accomplish this? Thanks!
Let me know if I need to post more code.
Here's a generic approach attaching declared functions to events.
function handler (e) {}
element.addEventListener('click', handler);
You're free to call handler everywhere, also inside $(document).ready, or if there's no other code in your DOMReady handler, you can just pass a reference as an argument:
$(document).ready(handler);
In your specific case you most likely want something like this:
$(document).ready(function () {
function handler (e) {...}
handler();
$("#update input").keyup(handler);
});
If the handler function uses the event object (e in the example), in modern browsers it's also available as a global event object, or in jQuery, e.originalEvent. The object doesn't exist if there's no event fired, though, in that case you've to pass a fake event object, containing the provided properties, to the handler, if it is needed.
I have a Chrome extension that intercepts and checks tweets before they get posted. To do this, I've add an event listener to the Tweet button. Sine the content is dynamic, I use the solution proposed in this thread:
initialize : function() {
let that = this;
let jsInitChecktimer = setInterval(checkForJsFinished, 111);
function checkForJsFinished () {
if (document.querySelector("div[data-testid='tweetButtonInline']")) {
clearInterval (jsInitChecktimer);
console.log("Button found");
that.addSubmitNewTweetClickHandler();
}
}
},
addSubmitNewTweetClickHandler : function() {
let that = this;
let buttonSubmitTweet = document.querySelector("div[data-testid='tweetButtonInline']");
buttonSubmitTweet.addEventListener('click', function(e) {
console.log("CLICK");
// Stop default event from happening
e.preventDefault();
e.stopImmediatePropagation();
// Do stuff
});
},
If the tweet passed the checks alright, it gets submitted by programmatically triggering the event using .trigger('click').
This works fine, but only once. After a tweet has been submitted and posted, the event listener on the Tweet button is gone, and I cannot intercept the next tweet to check it. I've tried calling initialize() after submitted again -- maybe the button gets removed and newly added to the DOM (it actually disappears fire a moment when submitting a tweet) -- but the querySelector finds the button immediately. But even after calling initialize() again, no click even on the Tweet button fires.
What could be the issue here? My problem is that I don't even know where to look for and how to debug this.
After many more hours, I've finally figured it out. The problem was essentially the highly dynamic content of the new Twitter website. After submitting a tweet, the Tweet button gets indeed removed and added again. In needed to do a serious of changes:
Use a MutationObserver to keep track of any changes. Every time there's a change, call the initialize() function. To avoid too many calls, I do this in case of certain changes (unnecessary detail here)
Change the addSubmitNewTweetClickHandler() method so that the event listener first gets removed in order to avoid duplicate listeners (please note that I use objects hence the use of this compared to my original question)
addSubmitNewTweetClickHandler : function() {
let that = this;
let buttonSubmitTweet = document.querySelector("div[data-testid='tweetButtonInline']");
buttonSubmitTweet.removeEventListener('click', this.handleSubmitNewTweetClick );
this.handleSubmitNewTweetClick = this.handleSubmitNewTweetClick.bind(this)
buttonSubmitTweet.addEventListener('click', this.handleSubmitNewTweetClick );
},
This change required to create the reference function handleSubmitNewTweetClick
Overall, it's still not a perfect solution since I call initialize() many unnecessary time. However, I failed to reliably identify when the Tweet button was added to the document. When I used the MutationObserver none of the added nodes had the attribute data-testid which I need to identify the correct button. I have node idea why this attribute was not there. Maybe the attribute is added some times after added to button, but even with an additional MutationObserver looking for attribute changes I could detect this.
Anyway, it works now and it's only for a prototype.
Still new to the forums, so I'll try my best to get across the problem. Basically I'm developing a mobile web app, and have several ontap functions for reloading the webpage after buttons clicked. Here is the code for two of my smaller onTap functions for demonstration purposes (so you don't have to sift through hundreds of lines of code). The licenses_button ontap function works perfectly fine, with no forms of errors whatsoever, but the back_button ontap function, and all other buttons that aren't created on the initial main page of the app won't act as button's and I have no idea why. Any advice? (I know the back_button has little to no content, I just removed a lot of it for debugging purposes and even this fails to work). Thanks for any advice!
$("#licenses_button").onTap(function(event){
$("#play_button").remove();
$("#banner").remove();
$("#licenses_button").remove();
$(".cloud").remove();
$(".cloudalternate").remove();
$("body").append("<div id='back_button'>Back</div");
});
$('#back_button').onTap(function(event) {
$('#back_button').remove();
});
$(selector).onTap(callback); attaches the handler to the selected elements at the moment it is called. Elements that are not yet created at this time cannot be selected (obviously since they do not exist yet) and thus, won't get the handler.
You need to attach the handler after you added an element.
For example:
$("#licenses_button").onTap(function(event){
$("#play_button").remove();
$("#banner").remove();
$("#licenses_button").remove();
$(".cloud").remove();
$(".cloudalternate").remove();
// Create the button.
var backButton = $("<div id='back_button'>Back</div");
// Append it to the body.
$("body").append(backButton);
// Attach the handler to the new button.
backButton.onTap(function(event) {
backButton.remove();
});
});
You mentioned the back_button and other buttons that aren't working are not created in the main page. Since these are created at a later time, you have to wait to set up the onTap event for those buttons AFTER you create the buttons. If you try to set the event handler up before they're created, they won't work.
I have a weird problem that I am not able to debug.
I have a script with the following relevant functions:
a function events() that has a jQuery.on('click', callback(event)) event binder inside it. That function gets called every time I add or remove anchors with AJAX, but that's irrelevant for this problem.
a function get_passwords() which gets jQuery.attr("href") from anchor $("a.active") and makes a $.post to the server with a callback that inserts values into a table upon receiving the data
The function get_passwords() is called synchronously in the callback(event) function like this:
event.preventDefault(); //prevents a browser navigation
$("a.active").removeClass("active"); //removes active class from all other anchors
$(this).addClass("active"); //adds a class "active" to the anchor that was clicked
get_passwords(); <---- the function in question <--BREAKPOINT #1
The function get_passwords() contains the following relevant lines:
$.post("url", postData, function(data) { //put received data into table }); <--BREAKPOINT #2
Now, the weird bug is that the get_passwords() function is called multiple times by the same event listener, and only stops calling that function after an arbitrary, but constant amount of times, every time the click is made on an anchor with the event listener.
I've set the breakpoint in FireBug on the above indicated line, and as I execute the script step by step, all it does is jump between the two breakpoints set above (the part where it calls get_passwords() and where it executes $.post, 4 times (always the same amount), up until the 4th time when it actually proceeds with the callback in the $.post function.
Realizing that there is no way I can ask anyone to read through all the code that I've written, does anyone have any suggestions as to where this bug could be coming from?
Thank you in advance.
EDIT: http://jsfiddle.net/nt3A4/
Are you looking for event.stopImmediatePropagation()?
#epascarello, #nbrooks,
You were both right. I was attaching multiple event listeners, somehow, to the same anchor. Probably got lost due to my poor coding planning (I was making up website features as I went along).
Anyway, I fixed it by pre-pending $("a").off() in the events() function, as to remove any other event listeners that may have been set before. Should of done that from the beginning :/
Thank you all for your answers and your time.
Before even starting, I know there already has been a thread about this, but unfortunately it did not help me at all.
So here is my problem, I have a loop written in JavaScript and at the end of it is a button click event. The event is related to a button situated inside a popup window.
for(var i=0; i<value; i++){
[...]
//some code here
[...]
//opens the window
windowButton.addEventListener('click', function(){
//code
});
//here I would like for it to continue once the click has been triggered
}
Unfortunately, it doesn't wait for the click.
Like said in the similar post, incrementing the variable i inside the function doesn't work, or even using a global variable. And the suggested answers are not what I am looking for.
[EDIT]
Okay, so I'm going to add some information to be more precise. I need to create a form. But it also needs to be able to parse a file containing all the information, and to be able to fill it. For each line of information of the file, so each time the form is completely filled, a window needs to open and wait for the validate button situated inside it.
Si I am hoping I made myself clear enough.
[/EDIT]
Thank you in advance for any reponse
There is no way to pause a function in JavaScript. You need to completely change your approach.
Move the code that you currently run each time you go around the loop into a separate function.
Create a variable outside that function.
Each time the function is called, increment that variable.
If the variable is "too big" return from the function before doing anything.
Assign that function as your click event handler.