I'm using Telerik UI for asp.net. Specifically I'm using RadTabStrip with partial page postbacks to allow the user to tab through different sets of data. When the user clicks a tab, some code executes and loads data just for that tab.
I've figured out how to execute codebehind: I set the OnTabClick property of the RadTabStrip, and then in codebehind I check what tab was clicked.
E.g.
protected void tab_Click(object sender, RadTabStripEventArgs e)
{
if (e.Tab.Text == "Info")
{
populateInfoTab();
}
}
private void populateInfotab()
{
// Do some stuff
}
However, I can't figure out how to execute client side javascript after a specific tab is clicked. What I tried:
Set OnClientTabSelected property, and then add some javascript:
function tab_ClientClick(sender, args)
{
var tab = args.get_tab();
if(tab.get_text() == "Info")
{
alert("Tab Clicked");
}
}
The problem is that I need to set the InnerHtml of some div in the clicked pageview after it is clicked. The div does not exist on page load (that specific RadPageView is hidden) so I cannot set it then. Once the user clicks into the tab, and after the page view loads, I need to be able to update the div's InnerHtml through JavaScript.
How would I go about doing this?
First option - if you do not set the RenderSelectedPageOnly property to true, all page views will be rendered on the initial load and you will be able to use JS to find/modify elements in them.
Second option - just set the content from the server as soon as you load the UC, this will usually make things simpler.
Third option - use client-side events (offered by the native PageRequestManager class or the RadAjaxManager, depending on how you setup your AJAX interactions) to execute when the response is received. The difficulty here is to determine which is the postback you need. Looking for the desired element and only executing logic if it exists is the simplest flag you can opt for.
Fourth option - register a script from the server code that will call your function, something like:
populateInfoTab();
ScriptManager.RegisterStartupScript(Page, Page.GetType(), "someKey", "myDesiredFunction()", true);
where you may want to use the Sys.Application.Load to ensure it is executed later than IScriptControl initialization.
Related
I'm using the ChromeWebDriver together with Selenium. The application is partically controlled automatically. Now I want the user to navigate to a page, where he has to choose a link from some list like
<ul>
<li>Google</li>
<li>Ecosia</li>
<li>Yahoo</li>
</ul>
I want to get the link automatically, where the user clicked on. As example, when he clicks on Google, I need some kind of event, that gave me http://google.de in C#. There exist a WebDriverEventListener, his ElementClicked event is exactly what I need:
private void EventDriver_ElementClicked(object sender, WebElementEventArgs e) {
if(e.Element.TagName == "a") {
string link = e.Element.GetAttribute("href");
MessageBox.Show($"User has clicked on link {link}");
}
}
But the big problem here: ElementClicked is only fired on clicks triggered by Selenium using C#. All events have this issue. For example, Navigated got fired after calling driver.Navigate().GoToUrl("http://stackoverflow.com"), but not after manually clicking on a link in the browser.
To solve this, I think its necessary to forward client-side JS events. Like this pseudocode:
$('a').click(function() {
SeleniumBackend.NotifyAboutClickEvent('a', $(this));
});
I know there is a method called ExecuteScript which allows to run JS in the browser. It seems possible to catch a direct return like
string jsReturnValue = driver.ExecuteScript("return 'test';");
For this case, that's not enough, since some sort of callback would be needed to be async.
object clickedLink = sharedWebDriver.ExecuteAsyncScript(#"
var callback = arguments[arguments.length - 1];
clickedLink('http://google.de');
");
That works, issue here: Only once. I can't bind an eventhandler, which notify me about later clicks...
It looks like you are creating the initial menu page. If that's true, you can just set a JS global variable using an onlick event and then use JavascriptExecutor to grab the variable setting and then use that to determine what link they clicked.
...or better yet, you can just detect the browser URL after they click and know where they went.
Simple web site with master page and multiple child pages.
In page_load, master page looks for session variable containing a value and if it's there, uses
Page.ClientScript.RegisterStartupScript(this.GetType(), "SessionAlert", "SessionExpireAlert(" + sessionTimeout + ");", true);
This kicks off a timeout alert, which works fine.
There is a server-side button on one child page that effectively ends the user interaction on the page and leaves a message stating "go and log in again if you want to do more stuff". When this button is clicked, I want to clear out the session variable (easy) and end the running timeout warning alert script (not so easy).
As the Master "page_load" event fires BEFORE the button handler, at the time the page reloads, it restarts the timeout script. When it hits the button event handler and clears the session variable, it's too late as the script is already running.
I've tried using "registerclientscriptblock" to inject immediate javascript to call the "clearTimeout()" client side function I have, but it doesn't seem to be able to find the function which exists on the master page and errors.
This seems to be a classic "chicken and egg" scenario and I can't see the wood for the trees. Could someone please point me in the right direction here before I drive myself mad!?
edited to add bit of javascript code:
Currently the master page function "SessionExpireAlert" referenced by the page_load code contains among other things this:
window.updateInterval = setInterval(function () {
seconds--;
document.getElementById("idleTime").innerHTML = convertTime(seconds);
document.getElementById("expireTime").innerHTML = convertTime(seconds);
}, 1000);
RegisterStartupScript will add the script to the end of the body, so the DOM is ready when it runs. As long as you always use RegisterStartupScript after that then the scripts will be added and executed in the order you create them.
Basically, RegisterClientScriptBlock is most likely going to place the script before any scripts added with RegisterStartupScript.
Have you considered putting this in Page_PreRender instead:
Page.ClientScript.RegisterStartupScript(this.GetType(), "SessionAlert", "SessionExpireAlert(" + sessionTimeout + ");", true);
With an appropriate check first to see if it is necessary?
I am trying to fix some issues in an old asp.net application which uses ASP GridView. There are several events bound to the grid. Say sort, row click etc. I want to execute some js function after load/reload completes, (like after sort using header click etc.).
I tried
JQuery's ready function, which fires only on page load.
Placed a script block next to the grid
Placed a RegisterStartupScript in grid_sort (where DataBind happens)
none of them fires on grid reload after sort.
Server-side events always cause a full page lifecycle. But if there are UpdatePanels in the mix then you may get a partial page postback which won't trigger a page load event. Keep in mind the full page lifecycle happens regardless.
When you want to execute some client side code after handling some sort of server side event, you need a way to pass some information to the JS/jQuery after the page fully renders. Usually this is done by using 1 or more <asp:HiddenField> controls.
Typically I will set its ClientIDMode to static to make life easier on the JS side of things. So for example if you have this:
<asp:HiddenField ID="hfSomeData" runat="server" ClientIDMode="Static"
Value="Something set after handling some gridview event"
then you can do this on the javascript side to access the value:
$("#hfSomeData").val();
The following code will execute PostBackHandler based on either the jquery ready event or call from endRequest as issued by an UpdatePanel partial page update
// Handle Full Page postbacks
$(function () {
PostbackHandler(0);
});
// Handle Partial Page postbacks
// i.e. when Gridview embedded in an UpdatePanel
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function(sender, args){
PostbackHandler(1);
});
//PostBackType : 0 for Full Postback
// : 1 for Partial Postback
function PostbackHandler(PostBackType) {
var passed_in_data = $("#hfSomeData").val();
if (PostBackType === 0)
// do postback stuff
else
// do partial postback stuff
}
Here's the situation: I have a variable number of dynamically created update panels on my page, so I thought I would write one method which handles all of the loading for each one.
My Updatepanel creation looks something like this:
Dim newUpdp As New UpdatePanel
newUpdatep.ChildrenAsTriggers = False
newUpdatep.UpdateMode = UpdatePanelUpdateMode.Conditional
newUpdatep.ID = Guid.NewGuid.ToString
AddHandler newUpdatep.Load, AddressOf updatep_load_method
updatep_Holder.ContentTemplateContainer.Controls.Add(newUpdp)
updatep_Holder.Update()
This creates the update panel and binds its load event to the method "updatep_load_method". This method is called as soon as the Updatepanel is inserted into the holder. The method code is as follows:
Private Sub updp_load_method(sender As UpdatePanel, e As System.EventArgs)
Dim div As New HtmlGenericControl("div")
div.InnerText = Date.Time.Now.ToString
sender.ContentTemplateContainer.Controls.Add(div)
sender.Update()
End Sub
A little later on I want to update the panel, and refresh the time. So I use the javascript __doPostBack method. According to Dave Ward, the __doPostBack method follows the full page postback lifecycle, so I figured the load event of my Update panel would be fired and that "updatep_load_method" would be called by that particular update panel...
Although the partial postback occurs, and other update panel's load events are called, my bound ones aren't. So what's happening here?
You need to recreate dynamic controls during Page_Init and have to use the same Id (so you cannot do a Guid.NewGuid.ToString() while recreating the control).
Otherwise, ASP.Net will not be able to locate your control and populate it with data from ViewState.
Here's a good article that explains more about dynamic controls.
Try implementing the RaisePostBackEvent method in your code:
protected override void RaisePostBackEvent(IPostBackEventHandler source, string eventArgument)
{
//call the RaisePostBack event
base.RaisePostBackEvent(source, eventArgument);
//add whatever code you need to execute on postback here
}
I am using an asp.net update panel to refresh the content on a page when a menu item is selected.
Within the content that is updated are images which have a javascript reflection function which is triggered with the following line of code:
window.onload = function () { addReflections(); }
This runs fine when the page is first loaded but not when a menu item is selected and the update panel is run.
On previous projects using jquery code I have replaced document.ready with function pageLoad but there is no document.ready on this page.
Like this:
<script>
// ASP.NET AJAX on update complete
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function(sender, args) {
// your code here, eg initToolTips('/Common/images/global/popup3.gif');
});
Basically, it's because that event isn't triggered by an update panel refresh.
There are ways to achieve this behaviour though, Ajax.Net has an EndRequestHandler function that you can hook into.
Here's a good example:
http://zeemalik.wordpress.com/2007/11/27/how-to-call-client-side-javascript-function-after-an-updatepanel-asychronous-ajax-request-is-over/
i think u should use
function pageLoad(sender, arg) {
if (!arg.get_isPartialLoad()) {
// in first load only
}
//every time the update panel refreshed
}
Regards
Take a look to this event:
http://msdn.microsoft.com/en-us/library/bb383810.aspx
window.onload is fired when the entire page is loaded. UpdatePanel uses an AJAX approach, so whenever it's updated and round trip ends, the page remains loaded and only a portion of this has been updated.
In other words, you need to do that "when a request to the server ends".