I have a usercontrol that can be used in for example a gridview itemtemplate, this means that the control might or might not be on the page at page load. In the case where the control is inside an itemtemplate i will popupate the gridview via asynchronous postbacks (via updatepanels).
The control itselfs registrers scriptblocks since it is depending on javascripts. First i used
Page.ClientScript.RegistrerClientScriptBlock
But this doesn't work on asynchronous postbacks (updatepanels) so i then tried the same using ScriptManager which allows me to registrer scripts on the page after async postbacks. great!.
ScriptManager.RegisterClientScriptBlock
However, ScriptManager (what i know of) does not have the functionallity to see if a script already is on the page, so i will for every postback generate duplicates of the script blocks, this is ofcourse unwanted behaviour.
I did a run at Google and found that i can call the Dispose() method of the PageRequestManager can be used, this does work since it clears the scripts and then adding them again (this also solves my issue with removing unused script blocks from removed controls).
Sys.WebForms.PageRequestManager.getInstance().Dispose()
However, ofcourse there is a downside since im posting here :).
The Dispose() method disposes the instance on the master page as well which leads to scripts running there will stop to function after an async postback (updateprogress for example).
So, is there a way to check if a script already exists on the page using ScriptManager or any other tools, that will prevent me of inserting duplicate scripts? Also, is there a way to remove certain script blocks (when i am removing an item in itemtemplate for example).
Big thanks in advance.
Try a function like this one:
Public Sub AddScriptToCompositeScriptSafety(ByRef manager As ScriptManager, ByRef script As ScriptReference)
For Each item In manager.CompositeScript.Scripts
If (item.Path = script.Path) Then
Return
End If
Next
manager.CompositeScript.Scripts.Add(script)
End Sub
If you set the same type and key attributes when registering then I think the SM will include only one of these.
Related
I you have a highly interactive event driven page in rails 5.0.0.1 with Turbolinks.
Having different interactions on different pages, events like window.resize will trigger on pages where I don't really need it.
Is it worth to sacrifice navigation time by disabling Turbolinks to serve page specific javascript, or should I not care and just use if statement in Jquery to check if certain elements are present in the page using their ID.
What is the rails way of doing this?
It is not recommended to serve page specific assets such as javascript. This slows down the user experience since navigating to a new page triggers another asset download.
The whole point of the Rails Asset Pipeline is to gather your assets, minify them and concatenate them all into a single file that the browser downloads only once, the first time a user navigates to your page.
Yes, use jQuery to check if certain elements exist to run some behavior.
The way I've found useful is to not think about js behaviors as page specific but rather, widget specific. e.g. if there's a sortable table in the DOM then initialize the sortable table widget i.e. $(".sortable").sortable()
The above example uses the jQuery plugins pattern. Place your behavior/widget logic inside the jQuery plugin and it will only run when the selector finds elements e.g. $("#nonexistant").something(), something() will not be called. $("#definitelyExists").somethingElse(), somethingElse() will be called.
In the preceding examples, when an element is found and the function is called, the this of the function references the matched elements and you can run your behavior logic on them.
I have an asp.net-mvc website where there is a top section with a bunch of filter information and the middle section is a reports. I now have a few different report formats and I want to toggle between a few reports. I have it working by making them all partial views and loading them via ajax (to avoid loading the common info over and over again) but one issue i realized is that some of the different reports have different javascript that goes along with them. For now, I am loading up all of the javascript files in the main parent page but I realized that I am wasting a lot of resources by download and wiring up all of the jquery events even if i never actually view a report
Is there anyway I can pass some javascript along with downloading a partial view in asp.net-mvc so I only load this and wire up the events "on demand" as required (instead of always)
Of course you can. Just be aware that the effects of the code will stick around even if you later remove the code itself: any functions you defined will remain defined, any listeners you attached will remain attached (as long as their target elements persist)... so it would be a good idea to make a setup() and teardown() methods for the loading code, that you'd invoke from your controlling code, rather than just drop a bunch of code to execute as it loads.
However, I would say it would need to be a rather unique set of circumstances for me to employ this method; for most part, it would be much easier and efficient to just load all the code you need at once, to benefit from client caching if nothing else. Toggle the behaviour of your code, don't toggle the code.
I have a couple of small javascript functions:
// Show cookie notice
$('#site-cookie-notice').slideDown();
// Hide cookie notice
$('.close-cookie-notice').click(function (e) {
if (e.preventDefault) {
e.preventDefault();
}
else {
e.returnValue = false;
}
$('#site-cookie-notice').slideUp();
});
The functions are only relevant to a single user control, that appears a maximum of once in a user visit (not at all for returning customers). The rest of the time the control is not rendered.
The above code currently resides in my global.js, inside the document.ready function, so loads every page, however it seems like this is wrong an uneccessary use of resource.
I'd be interested to know if there is a better approach to registering this code on such an adhoc basis.
You can use the ScriptManager class to register scripts in the load of your user control. This can also be used to ensure that the script isn't loaded more than once.
You can use either RegisterClientScriptBlock or RegisterClientScriptInclude depending on whether you want to provide the script in-line or have it in a separate file.
Use the ScriptManagerProxy in the user control to reference this script. That will include it on your page without having to have it on all pages.
This requires a ScriptManager or ToolkitScriptManager (if using AjaxControlToolkit) on your master page or content page. You can only have one script manager per entire rendered page.
http://msdn.microsoft.com/en-us/library/system.web.ui.scriptmanagerproxy.aspx
I am working on a custom control that is being used on a webpage that contains many updatepanels. In my custom control, there is extensive use of jquery and many plugins are used as well. Now, on every updatepanel's postback, THE CONTROL GETS RENDERED AGAIN AND AGAIN, it loads the javascript resources again too, but doesnt call the javascript functions again. This is causing problem that many elements in my control which has to be turned in to one thing or another by jquery plugin are not working(javascript functions not calling in simple).
Now I have tried many solutions, including the ones mentioned in this question
How to have a javascript callback executed after an update panel postback?
but in vain. Previously, when my page contained only one updatepanel,
pageLoad(sender, Args);
functon was working fine, now in the case of multiple updatepanels that is not working, neither
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_pageLoaded(pageLoaded);
function pageLoaded() { }
If you don't want your control to refresh on every UpdatePanel's postback - set UpdateMode for the UpdatePanel that hosts your control to Conditional this way it will be refreshed only when its own trigger or child control fire (Ref: http://msdn.microsoft.com/en-us/library/system.web.ui.updatepanel.updatemode(v=vs.90).aspx).
That said, you don't have to manually add pageLoaded event handler on client side. Use intristic pageLoad function which fires on every page load be it via UpdatePanel or otherwise (Ref: http://msdn.microsoft.com/en-us/library/bb386417(v=vs.90).aspx)
One other way to fire a JS function is from server-side code. Every time your control loads or performs some server-side init - use ClientScript.RegisterStartupscript call to make sure JS function will be called on the client afterward, for example
ClientScript.RegisterStartupscript(this.GetType(),"myFunc", "myFunction();", true);
Ref: http://msdn.microsoft.com/en-us/library/z9h4dk8y(v=vs.90).aspx
After searching online with multiple different keywords, I haven't been able to find the solution to my problem.
I started by looking for a way to popup a message asking for a user to renew their session a minute before it cancels. The solution I decided to use was the run a javascript timer in the masterpage and have it be called on a Masterpage.Page_Load(). In this way, whenever my user navigates from page to page, they reset the timer. However, because many of the pages the user will be using have updatepanels and update asynchronously, the function I am using is being reached, but being skipped over (according to the debugger).
The function I am using is:
ScriptManager.RegisterStartupScript(main, this.GetType(), "callTimer", "callTimer();", true);
This function runs fine on a regular postbacks, or asynchronous postbacks on the masterpage (I update the timer by doing a postback on a updatepanel in the masterpage), however, will be skipped on asynchronous postbacks.
I have tried a few things, making the control of the function Page or the UpdatePanel in the masterpage or the updatepanel in the childpages. I have tried putting this code in the childpages as well, but while these change do reset the timer, it causes the javascriptcode to run multiple times and they fight over the label displaying the countdown.
I'm really at a loss here. I think a possible solution would be to change the startupscript's control and terminate all javascripts running before that code again. However searching for a way to terminate, cancel or stop javascript functions programatically yields no useful results as well.
Another solution I would be okay with is reseting the timer on mouse movement, but since I'm designing for IE8, this will not work unless the window is out of focus.
You need to inject the script through the ScriptManager in the case of a partial postback or it will not be re-executed. Here's a utility function (vb.net) to handle the injection logic for you:
Public Shared Sub InjectScript(ByVal containingPage As Page, ByVal scriptKey As String, ByVal scriptText As String)
Dim sManager = ScriptManager.GetCurrent(containingPage)
If sManager IsNot Nothing AndAlso sManager.IsInAsyncPostBack Then
//the page is being partially-posted back by an Ajax control (e.g. UpdatePanel)
ScriptManager.RegisterStartupScript(containingPage, GetType(Page), scriptKey, scriptText, True)
Else
//standard postback
containingPage.ClientScript.RegisterStartupScript(GetType(Page), scriptKey, scriptText, True)
End If
End Sub
I found a solution to the problem: I was able to solve this by sending the current date.time as a number to the javascript function. from there I set the value of the countdown label to the date.time. there, during my timer if I found that the date.time of the label didn't match the one that the function started with, it would return and end the function. This meant that only the latest instance of the function would remain running at any given time.