I have an ASP.NET page which sometimes does not generate the expected "WebForm_AutoFocus()" javascript, even though I am explicitly calling .Focus() on one of the controls. Are there any known scenarios where some factor would prevent that javascript from being generated?
Specifically, when the user clicks a particular button, I'm creating some new controls dynamically: in this case a text box. In OnPreRender I'm grabbing that newly-created control and calling .Focus() on it. The idea is, when the postback completes, the browser gives focus to the newly-created textbox control. However, the generated HTML (verified via firebug and fiddler) simply does not contain a WebForm_Autofocus call at all.
In other scernarios, the same page (on postback or on initial hit) calls .Focus() on a different control - one which is not dynamically created; in those cases the WebForm_AutoFocus() script is generated perfectly, and all is well.
Unfortunately, I'm working on a client system that LOVES frameworks upon frameworks, and abstractions upon abstractions, so I cannot post a meaningful/concise code sample here. However, if any of my friendly SO'ers knows more about generation of that "WebForm_AutoFocus" javascript - and scenarios which would prevent it from being generated - that would give me a good place to start digging.
The autofocus call only gets included if asp.net thinks there is a need for it. Set a default button on the page so that asp.net will know to make the method.
Related
I did the following:
Created a Google Form (e.g. form ID = ABC)
Created a Google Sheet (let's call it sheet1)
In sheet1's script editor, installed a trigger to my form with code such as the following:
var form = FormApp.openById("ABC");
ScriptApp.newTrigger("testFunctionSheet1").forForm(form).onFormSubmit().create();
When I call the following, I see my trigger was installed properly:
ScriptApp.getUserTriggers(form);
Everything is great. I can execute code whenever a Google Form is submitted.
Problem is, later on I go ahead and create a new Google Sheet (let's call it sheet2), which has similar code:
ScriptApp.newTrigger("testFunctionSheet2").forForm(form).onFormSubmit().create();
To be safe, though, I attempt to remove all the previous triggers from all my old scripts (i.e. sheet1). However, when I run:
ScriptApp.getUserTriggers(form);
... it returns one result (testFunctionSheet2) instead of returning both testFunctionSheet1 and testFunctionSheet2. Turns out it only returns triggers that are executed by the current script!
This is problematic because it may mean I accidentally have many scripts that are all executing upon a form's submission. If I never wrote down which scripts execute for which forms, I would have no idea what exactly is run from each submission. Some of those scripts may either do the same thing (which is a waste of CPU cycles at best, or will interfere with each other at worst), or they may do completely different things and potentially clash with each other.
I want a simple way to find all script triggers that will be executed on form submission. Something like if the function actually behaved as I would expect...
I.e. ScriptApp.getUserTriggers(form) should return something like:
sheet1: testFunctionSheet1
sheet2: testFunctionSheet2
This way I can easily tell which scripts will be executed upon form submission and can manually remove the old ones, to ensure nothing clashes.
Is there a way to find out which triggers will execute across all my scripts upon form submission?
Update: The documentation for getUserTriggers() clarifies that it will never return triggers for different scripts:
Gets all installable triggers owned by this user in the given form, for this script or add-on only. This method cannot be used to see the triggers attached to other scripts.
How, then, would I know all triggers associated with a given Google Form? Note: this doesn't necessarily have to be a programmatic solution. If there was a UI element in Forms that gave me this information, that would suffice too.
There doesn't seem to be a way to do this, but there are some workarounds that can make things a bit more organized:
Instead of installing the form trigger on a Sheet, install it on the Form. If you get into this habit, you can easily tell if there are scripts installed because the first place you'd check is in the Form's script. Simply run the get all triggers command as you tried above, and it'll work.
Instead of installing the form trigger on a Form, set the form to submit its responses to the Sheet, and use the onFormSubmit() method in SpreadsheetTriggerBuilder. To find out which trigger is associated with a form becomes as simple as opening the form, then going to its destination, and then looking if that script has a trigger for the form.
Hide the trigger script names in some property on the Form that you don't plan on showing to the user (e.g. customClosedFormMessage). Set it to something like This script has an active trigger associated with sheet1. You can create a helper function that before installing a trigger, it ensures that that text doesn't exist there (if you want to limit to 1 trigger per form, for example).
Go to https://script.google.com/home/triggers?trigger_type=3&document_id=ABC
That should give a list of all triggers from form with id ABC. You can clear filters there and add new filters.
As the OP already mentioned on the question, the documentation says that a script can't get triggers created by other scripts.
If you are the only one that create triggers from your script projects, then go to https://script.google.com > Triggers, there you will find a list of all the triggers created by your account.
I didn't tried it yet, but I think that one alternative is to enable the Google Apps Script API on the projects that create triggers and add a function to be called through Google Apps Script API to "log somewhere" the triggers created by that project.
Regarding to "log somewhere" maybe the easier setting is to email the log to the "active user".
I'm trying to get an html button to call a server-side method like this:
<button onserverclick="onClick" runat="server">Submit</button>
However, this call is not being made when the browser's javascript is disabled.
I am confused because my understanding is that this call has no interaction with javascript.
The __doPostBack() method is responsible for raising a click event to the server in the background. With JavaScript disabled there's no way that's going to happen.
Here's one of the many articles that explains how this works. And a related question here which gives a glimpse into what code is generated behind the scenes.
In web development, JavaScript is often executed when clicking on elements.
In both Internet Explorer 9 and FireFox 4 a little message pops up in the bottom left hand corner with the JavaScript function will be executed by clicking on elements these elements.
ASP.NET makes use of the JavaScript __doPostback(...ugly parameter names..) on almost every element that sends a request to the server. This JavaScript is automatically added to the HTML elements that are generated by the ASP.NET controls and I have no way to circumvent this.
For example, an ASP.NET DropDownList is rendered as an HTML Select element and the __doPostBack() method is added to it so that whenever the user selects a new element, the server can process this action.
The __doPostaback() method is embedded into many of the ASP.NET controls and there is no easy way to change this.
One of my end users commented that this new feature makes it feel as if they are in "Debug-mode"....
So, my question is: how do I either make this popup show something user friendly...or is there a way to tell the browser (via HTML) not to display this nastiness?
Thanks!
-Frinny
Why don't you make the href of the link a hashtag and attach the actual action via JavaScript:
HTML
<a id="foo" href="#foo">Foo</a>
JS
var foo = document.getElementById('foo');
foo.onclick = function(e){
//script foo!
return false;
};
Your location will still be #foo to look nice, but the actual action will be in the foo.onclick function.
Alternatively you can specify the event inline (Foo), but I try to keep a clear MVC separation with HTML, CSS, & JS.
Using a hashtag also gives you the ability to listen for hash-change events or check the hash tag onload so that a user can still middle-click a link and have it work correctly in a new tab.
To my knowledge there isn't a way to make it not display, as that is part of the browser and not the page.
What I would do is create javascript functions at the top of the page with user readable names that contain the other functions inside.
I had problem triggering server side button click events so I found a solution on the net that I should do something like
<input type="submit" name="button" id="loginButton" value="Submit"
class="button-orange" alt="Register" title="Register" runat = "server" onclick ="this.disabled=true;__doPostBack('loginButton','')"/>
I did it, and it worked, but I would like to know what is going on!
Check this article:
Understanding the JavaScript __doPostBack Function
This method is used to submit (post back) a form to the server and allows ASP.NET framework to call appropriate event handlers attached to the control that raised the post back.
You usually (in simple scenarios) don't use the method directly - it is internally used by the controls you drop on the page.
The parameters passed to this function are stored in a hidden field and picked up by ASP.NET framework on the server-side in order to find the control that raised the post back.
simply said, it is used mainly by controls with AutoPostBack property
http://www.dotnetspider.com/resources/189-AutoPostBack-What-How-works.aspx
if you want to implement autopostback for your custom control, then you need to implement IPostBackDataHandler
The solution might be working but it's not a real fix.. better way will be to find why the button events are not triggering and fix the core of the problem.
Now to answer your questions.. PostBack is the term used to describe when the form is being submitted (posted) back to the same page. Simple as that.
Ordinary submit button would have been enough, but part of PostBack is the ability to identify which control triggered it, meaning what button or link was clicked.
To do such a thing ASP.NET is automatically adding hidden fields to the form and when clicking on element that should cause PostBack, JavaScript code is used to update the values of those hidden fields to the proper values indicating what was clicked - the argument you pass.
The name Microsoft chose to give to the JS function doing the above is __doPostBack - it's just a name of a function, ordinary JavaScript function that ASP.NET automatically writes to the browser.
Hope things are bit more clear now.
I'm trying to manually call the ASP.NET (3.5) javascript postback function __doPostBack from my javascript code. The problem is that the postback script block, that is normally rendered right after the beginning of the <form> tag (and the hidden fields), is occasionally rendered near the closing </form> tag.
Is there any way to force it to be rendered near the beginning of the form tag? Also, how does ASP.NET decide when/where to render the postback client script block?
Edit > Additional Info:
The javascript code resides inside a user control that references the __doPostBack function. The control itself does not contain any 'postback controls' that would call that function. (When I mention 'postback controls', I mean ASP.net controls that call the __doPostBack function and not the asp.net ImageButton and Button controls)
Based on what I've observed and #Brian's comment on the dependency of the postback script on the availability of 'postback controls' on the page, I've found that when the page contains controls that cause postback, the __doPostBack script block is rendered after the opening <form> tag and when there are none, it renders them near the closing </form> tag (or according to this it's not even supposed to be rendered). Now it would make sense for ASP.NET not to render the postback script if there are no controls that require it, but the apparent position of the script near the closing tag is the one that still eludes me. I haven't been able to find any documentation that suggests this behavior. All I've been able to find was this.
Having said that, I've found a couple ways around this issue:
Add a 'postback control' and set its visibility to hidden via css (not the Visible property). eg. <asp:LinkButton ID="RequirePostBackScriptLink" runat="server" style="display:none;" /> (this is what I'm using)
Add the control to the Page.RegisterRequiresPostBack and implement the IPostBackDataHandler interface.
Finally, as #Jonathan_Bates mentioned in his post, the proper thing to do is to wrap the reference to __doPostBack inside a function that is an event handler to load (or ready if you're using jquery). That way, there wouldn't be a need to depend on the actual placement of the __doPostBack script.
It'd be great if anyone can provide more info on this, aforementioned, behavior.
I am guessing that where it renders is important to you so that your scripts render after it and can invoke it (which let me say up front, is a bad idea to begin with).
You just need to make sure that whatever script you are using to call __doPostBack calls it after its been read into the browser. If you use a library like jQuery and its $(document).ready() convention, you can be sure that your code won't execute until all other code is loaded, and therefor your code would be able to call __doPostBack.
Some of it is controlled by the controls that render, whereas the page injects the client script blocks and startup scripts at a pre-defined point...
I assume this is for a control or something? This isn't for a standard block?