I've spent at least 2 days trying anything and googling this...but for some reason I can't get RegisterClientScriptInclude to work the way everyone else has it working?
First off, I am usting .NET 3.5 Ajax,...and I am including javascript in my partial page refreshes...using this code:
ScriptManager.RegisterClientScriptBlock(this, typeof(Page), "MyClientCode", script, true);
It works perfectly, my javascript code contained in the script variable is included every partial refresh.
The javascript in script is actually quite extensive though, and I would like to store it in a .js file,..so logically I make a .js file and try to include it using RegisterClientScriptInclude ...however i can't for the life of my get this to work. here's the exact code:
ScriptManager.RegisterClientScriptInclude(this, typeof(Page), "mytestscript", "/js/testscript.js");
the testscript.js file is only included in FULL page refreshes...ie. when I load the page, or do a full postback....i can't get the file to be included in partial refreshes...have no idea why..when viewing the ajax POST in firebug I don't see a difference whether I include the file or not....
both of the ScriptManager Includes are being ran from the exact same place in "Page_Load"...so they should execute every partial refresh (but only the ScriptBlock does).
anyways,..any help or ideas,..or further ways I can trouble shoot this problem, would be appreciated.
Thanks,
Andrew
Here's the key:
partial page refreshes
You have to jump through special hoops to add javascript to a page after the initial load, because loading javascript later is considered a security risk by some (it's also bad for Google indexing).
Instead, register the scripts on the initial page load and just don't execute the scripts until later. If these scripts are created dynamically, I suggest you factor out the static portion and refactor as methods you can call with information returned dynamically from your page refresh.
Related
Updated - Title changed b/c StyleSheetTheme and Theme have nothing to do with it -- see answer for details.
I'm working on a page that has descended, through several years and a few intermediary stages, from another page that successfully uses the AJAX pageLoad() function to perform some (re-)initialization on full and partial postbacks.
The pageLoad() on this new page was not firing. A systematic comparison of the two pages (.aspx and .js files) eventually led me to a surprising (to me, anyway) difference that was causing the failure: the old page's # Page directive specified a Theme="foo", whereas the new page's directive specified a StyleSheetTheme="foo". Changing StyleSheetTheme to Theme restores the triggering of the pageLoad() function.
In this new page I can live with the (non-overridable) Theme settings, so I don't actually have a problem that needs solving in this momemt, but I thought the behavior was not obvious and worth noting, and if someone has insight into the reason(s) StyleSheetTheme might block firing of pageLoad() I would like to know.
Further investigation with the page referenced in the question as well as other similar pages revealed that the problem had nothing to do with changing between the StyleSheetTheme and Theme attributes of the # Page directive. I changed the question/title to reflect this.
The actual reason the pageLoad() function was not being triggered in the particular Javascript file I was working on is that there was already another pageLoad() function defined in a separate Javascript file being used by the page, and it was the one being executed because it was included later and over-rode/replaced the one I was working on. I found this using a script debugger by locating the pageLoad handling within the ScriptResource.axd file (in function Sys$_Application$raiseLoad()) and following execution into the second, over-riding script file... Palm, meet forehead...
Takeaway points:
only one pageLoad() can operate at the page level without resorting to some kind of scheme to daisy-chain multiple scripts; I opted for this approach so each of my script files can add its own (re-)initialization to the chain without clobbering any that are already there
using the StyleSheetTheme attribute vs the Theme attribute had nothing to do with my problem
try to be (even more) careful to ensure clear and clean tests before posting to SO... I thought that I had done a simple A/B test of the page directive attributes and that it had solved the problem, but upon discovering the true cause I went back to review the screen-captures (I use for time-tracking) and discovered that I had made two changes, not just one, before observing the change in behavior. It was the other change (removing another Javascript file from my page) that had fixed it, but during an interruption between the changes and final testing I forgot that I'd done it
After much banging of the head and manual line-by-line code removal, I have figured out that a RegisterClientScriptInclude call inside an ASCX web control is causing multiple page_load events to fire. This only happens when the ASCX is included on some pages, but not others.
Removing this line of code causes the double-postback to stop:
Page.ClientScript.RegisterClientScriptInclude(
Page.GetType(),
"[SCRIPTNAME]",
"[SCRIPTFILE].js")
I also tried this without including Page.GetType(), to no avail.
That line of code shouldn't be causing multiple page loads... There's probably something else going on... I would turn on Tracing at the page level and throw some Trace.Warn statements in to see what's going on...
But I'm not a big fan of the Page.ClientScript.RegisterClientScriptInclude() method and find that it's usually easier just to include the .js file in the parent aspx page... It's a very mild performance hit if that .js file isn't needed on a particular page...
I think I summed up the question in the title. Here is some further elaboration...
I have a web user control that is used in multiple places, sometimes more than once on a given page.
The web user control has a specific set of JavaScript functions (mostly jQuery code) that are containted within *.js files and automatically inserted into page headers.
However, when I want to use the control more than once on a page, the *.js files are included 'n' number of times and, rightly so, the browser gets confused as to which control it's meant to be executing which function on.
What do I need to do in order to resolve this problem? I've been staring at this all day and I'm at a loss.
All comments greatly appreciated.
Jason
If the issue is simply that the same file is being embedded multiple times and causing conflict, look into using RegisterClientScriptInclude. If you use the same identifier for all of your calls to RegisterClientScriptInclude only one instance of that file will be embedded:
http://msdn.microsoft.com/en-us/library/2552td66.aspx
However, if the issue is that your methods are being called but they don't know what controls on the page to operate on then you need to figure out how to provide your JS some context. Define a JavaScript object that represents your control on the client-side, and on the server-side emit the call that will instantiate it with the client IDs of the controls you'll be operating on.
We are using CustomValidator to validate User Control. The control works fine until you drop two instances of the Control on the same page, since they reference the exact same JavaScript functions, only one control works. Work around, we appended JavaScript function name with control id.
Validate_SAPDepartment<% =ControlId %>(oSrc, args) {...}
In codebehind, we assinged ClientValidationFunction
CustomValidator1.ClientValidationFunction = "Validate_SAPDepartment" + this.ControlId
This may not be the right approach but it works.
I've had this situation before. You register a separate JavaScript file with the page using the ScriptManager. You can stream this as a resource file embedded into the dll if you wish.
Then you only call into the functions from your control.
Otherwise a completely separate jquery file may also work.
I am trying to make use of the yahoo exceptional performance rule : avoiding duplicate script
To do so i would like to be able to know whether or not a script was already added to the page before injecting it in the page. It looks like i can't figure what has been added in asp.net code behind unless i have a scriptmanager added to the page. but i would like to avoid using asp.net AJAX. From the description of the rule, it looks like it is something possible in php though.
Assuming that i can't do the check in my code behind, i was considering using jQuery $.getString function but it doesn't check before fetching the script. If i was to choose the javascript file, would i have to parse the whole http response in order to figure out which script was loaded on the page?
If the page is registering the scripts with the ASP.NET Page.ClientScript Register APIs then you can use Page.ClientScript.IsClientScriptIncludeRegistered. On the other hand, if you are using those APIs you don't really need to call it, since it already ensures only one of each is registered.
http://msdn.microsoft.com/en/us/library/system.web.ui.clientscriptmanager.isclientscriptincluderegistered.aspx
If the page just has regular ole script elements statically in the markup, and you need to detect if a script is loaded on the client side, you will have to get all the script elements on the page and look at their .src values. The thing with that is that some browsers automatically resolve that url to a full path, not just the one you declared. So, you can account for that in various ways -- you can just search for the end of the string being the script you want, or you can cause the url you want to compare with to also be resolved by setting it onto a dynamically created script element (which you never add to the DOM but is still resolved for you).
This is just off the top of my head, sorry if I get something wrong:
var s = document.createElement("script");
s.src = "foo.js";
var loaded, scripts = document.getElementsByTagName("script");
for (var i = 0; i < scripts.length; i++) {
if (scripts[i].src === s.src) {
loaded = true;
break;
}
}
if (loaded) {
// this script is already loaded
// assuming you dont have multiple copies in different locations
}
You don't need to use any client-side scripting to do this... you can do this in your code behind using the ClientScriptManager without needing to make use of ASP.NET AJAX (I think you're confusing ClientScriptManager with ScriptManager*) in your control/page just use:
ClientScript.RegisterClientScriptInclude("some-script", "myScript.js");
or from your user controls:
Page.ClientScript.RegisterClientScriptInclude("some-script", "myScript.js");
This will use the key "some-script" & only register one copy of the script on the page.
*To be clear I think the confusion is arrising from the difference between these:
ClientScriptManager if a server-side helper class which is used to manage client side scripts (in other words its whole purpose is to do exactly what you are trying to do). It is accessed via the Page's ClientScript property.
ScriptManager is a Control used to aid client side Ajax scripting in ASP.NET AJAX
(hell I even confused myself & gave the wrong example code initially)
well that wouldn't actually work in a master detail scenario with multiple web user controls.
Then you wouldn't have control over who has to do the script initialization if the web user control is dynamic.
It's easier to link once, but a developer would have to weigh his options between ClientManager and using a script load.
yeah you have to parse the whole response...
why don't you create a javascript file and put all of your javascript there and then import that javascript file in your code??? in this way you can get rid of duplicate script insertion.
I have a problem that is really making me feel dumb. I have a custom control that inherits textbox. This textbox (at least for this example) simply has a .js file that is embedded in the .dll.
Long story short, works great when not in an AJAX update panel. So i did some research and found that instead of using: Page.ClientScript.RegisterClientScriptResource, i should use ScriptManger.RegisterClientScriptResource - i have done this in the overrdive render method, but the javascript still does not fire.
Anyone know what im doing wrong?
example:
i have a folder in my project called Scripts - it contains myscript.js
My Assembly is called Jim.Bob.Controls
I add attributes to my controls ie: Attributes.Add("onclick", "Test2();");
In the Override Render:
ScriptManager.RegisterClientScriptResource(this.Page, typeof(CustomTextBox), "Jim.Bob.Controls.Scripts.myscript.js");
Yet i still get 'object expected' error.
I need my textbox to work with and w/o AJAX. I imported System.Web.Extensions into my project to access ScriptManger
Can someone please tell me what im doing wrong? Again, this whole thing worked fine w/o AJAX, i have put the necessary stuff into the AssemblyInfo.cs (WebResource:,,,,etc)
Thanks in advance :-)
--- UPDATE ---
I reverted the control, trying it in a non AJAX web and i am having the same problem. Not sure why i have a problem, i have another custom control in the same assembly that is working just fine - have them setup the exact same way, only difference is the one that is working inherits WebControl, the one that is not inherits TextBox
...
in the one that is working i emmit html like Go and do it
Where the one that is NOT working i have
Attributes.Add("onclick", "CustomFunction();");
Also, if i do Attributes.Add("onclick", "alert('hello');");
it works fine.
Sorry for such a long post.
Try to pass this instead of this.Page. The ScriptManager would output scripts only for controls which are being updated (children of UpdatePanel that is).
I've just noticed that you are doing this during Render. That's too late. Try PreRender instead.