Run Js function only once after 2 seconds from c# code behind - javascript

Hello i have the next question, ive got the next function =
protected void lnk_Click( object sender, EventArgs e )
{
LinkButton btn = sender as LinkButton;
string text = btn.CommandName;
ScriptManager.RegisterStartupScript( this, GetType(), "script", "alert('"+ text + "');", true );
}
I want to run the function after a second or 1.5 secs because this is running before the page renders visually, causing a "visual bug" on which the li tags (for example) dont get the css properties.
Any suggestion would help, thanks!

The JavaScript content should run on the event DOMContentLoaded like this:
document.addEventListener("DOMContentLoaded", function(){alert('text');});
If you're sure you want to use the "dirty" way, use setTimeout:
setTimeout(function(){alert('text');}, 1500); // 1500 milliseconds

In async you can wait using Task.Delay
private async Task<Response> ExecuteTask(Request request)
{
var response = await GetResponse();
switch(response.Status)
{
case ResponseStatus.Pending:
await Task.Delay(TimeSpan.FromSeconds(2))
response = await ExecuteTask(request);
break;
}
return response;
}

Related

document.getElementById returns a null value, but only when executed within a multiline script. Returns correct element when executed by itself

I am creating a script to automate a data entry process on a server monitoring website. The site does not have an API for this specific data entry type, so I am using JavaScript to automate the mouse clicking and data entry process.
The script returns the correct document.getElementById("") value for getElement statement. However, it only returns the correct value whenever I manually execute line of individually. If I run the entire script, then the code breaks on one single line.
`var namesAndAddresses = { 'DomainName': 'IP' };
//Function to press sidebar "add device button"
function MenuFunction() {
MenuId = document.getElementById("menurow_Add/Import Devices").firstChild.nextElementSibling;
MenuId.click()
}
//Function to press "add device manually button"
function AddDeviceFunction() {
AddDeviceButton = document.getElementById("addDeviceButtonId_label");
AddDeviceButton.click();
}
//Function to add device information and then press the save button
function AddDeviceInformationFunction(domain, address) {
FQDN = document.getElementById("deviceNameId").value =
domain; //FQDN;
deviceClass = document.getElementById("deviceClassId").value =
"Switch/Router";
OS = document.getElementById("deviceOsId").value =
"Other Operating System";
ipAddress = document.getElementById("customUriId").value =
address; //DictionaryID;
licenseMode = document.getElementById("licenseModeId").value =
"Professional Mode";
saveButton = document.getElementById("cancelButtonId"); //change to save button
saveButton.click();
}
//manually wait function
function pause(milliseconds) {
var dt = new Date();
while ((new Date()) - dt <= milliseconds) { /* Do nothing */ }
}
//For loop to add each domain and ip that is listed in the dictionary
for (var [domainName, IP] of Object.entries(namesAndAddresses)) {
window.self = document;
//Function to press sidebar "add device button"
MenuFunction();
//Insert wait for sub-page to load here
pause(3000);
//Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
AddDeviceFunction();
//Insert wait for objects to load here
pause(5000);
//Function to add device information and then press the save button
AddDeviceInformationFunction(domainName, IP);
//Insert wait for objects to load here
pause(5000);
};`
HTML code is below:
enter image description here
I have tried adding in a manual "wait" because window.onload does not work due to all the HTML being loaded already. I also tried adding a try/catch statement within a loop, so that it could make the attempt 10 times over a period of 10 seconds. That didn't work either.
Your code's pause function is blocking.
What this means is that since it "waits" using a while loop, it is not actually waiting but doing a lot of useless work, using up 100% of the CPU, and preventing anything else from actually loading.
Because of this, I can only presume the elements that are supposed to appear when loading do not get a chance to, meaning getElementById returns null (they do not exist yet)
Consider using something like setTimeout, which will properly wait, without preventing other work from being done.
Replace your for loop near the end with
var entries = Object.entries(namesAndAddresses)
window.self = document;
function processEntry(){
if(!entries.length){
// Done
return
}
// Get (and remove) the first element in the array
var [domainName, IP] = entries.shift()
//Function to press sidebar "add device button"
MenuFunction();
//Wait for sub-page to load using setTimeout, which will run this code after 3000ms
setTimeout(function(){
//Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
AddDeviceFunction();
//Wait for objects to load here
setTimeout(function(){
//Function to add device information and then press the save button
AddDeviceInformationFunction(domainName, IP);
//Insert wait for objects to load here
setTimeout(function(){
// Done, go to next entry
processEntry();
}, 5000);
}, 5000);
}, 3000);
};
processEntry()
I would also recommend looking into promises and async/await, which can make this code look much neater:
function pause(milliseconds) {
return new Promise(function(finish){
setTimeout(finish, milliseconds)
})
}
async function processAllEntries(){
//For loop to add each domain and ip that is listed in the dictionary
for (var [domainName, IP] of Object.entries(namesAndAddresses)) {
window.self = document;
//Function to press sidebar "add device button"
MenuFunction();
//Insert wait for sub-page to load here
await pause(3000);
//Function to press "add device manually button" **THIS IS THE FUNCTION THAT RETURNS NULL**
AddDeviceFunction();
//Insert wait for objects to load here
await pause(5000);
//Function to add device information and then press the save button
AddDeviceInformationFunction(domainName, IP);
//Insert wait for objects to load here
await pause(5000);
}
}
Your pause causes the UI not to be able to render. You can make a function that uses await to look for an element. As soon as it is available it will update.
function addElem() {
const div = document.createElement('div');
div.className = 'foo';
div.textContent = 'hello';
document.body.append(div);
}
const waitForElem = (selector) => new Promise((resolve, reject) => {
const check = () => {
const elem = document.querySelector(selector);
if (elem) {
resolve(elem);
} else {
window.setTimeout(check, 1);
}
};
check();
});
window.setTimeout(addElem, 5000);
(async function() {
const el1 = await waitForElem('#bar');
el1.textContent = 'found 1';
const el2 = await waitForElem('.foo');
el2.textContent = 'found 2';
})();
<div id="bar">Test</div>

How can I change cursor to wait icon in Visual Studio asp.net?

I have a Web Forms project in VS 2013 in which I call an asynchronous process from a button within an update panel. I would like the wait icon to show while the asynchronous process is running.
I am using the code- behind shown below, but the cursor does not change from the default pointer when cmdAutoCaption is clicked. However, after the asynchronous process has completed and content_string returned, the cursor changes to a wait icon if it is moved outside the update panel.
protected void cmdAutoCaption_Click(object sender, EventArgs e)
{
string sUser = AuthoriseUser();
if (sUser == "") return;
string script1 = "document.body.style.cursor = 'wait';";
ScriptManager.RegisterStartupScript(this, GetType(), "ServerControlScript", script1, true);
CreateAutoCaption();
}
private async void CreateAutoCaption()
{
await MakeAnalysisRequestAsync(Session["strImagePath"].ToString());
}
private async MakeAnalysisRequestAsync(string imageFilePath)
{
...
response = await client.PostAsync(uri, content);
// Get the JSON response.
string contentString = await response.Content.ReadAsStringAsync();
...
string script1 = "document.body.style.cursor = 'auto';";
ScriptManager.RegisterStartupScript(this, GetType(), "ServerControlScript", script1, true);
...
}
You can use the following code to change the cursor:
Cursor.Current = Cursors.WaitCursor
This should solve your problem.

Waiting for element visibility instead of page load with Neustar WPM

I am trying to write a Neustar WPM script to measure the time taken from clicking a button to the appearance of a button in a overlay that opens. The script looks something like below.
var webDriver = test.openBrowser();
var selenium = webDriver.getSelenium();
webDriver.get('https://www.mywebsite.com');
selenium.waitForPageToLoad(30000);
// Start logging HTTP traffic and timings
test.beginTransaction(); 
test.beginStep("Open SignUp");
selenium.click("link=Sign Up");
selenium.waitForElementPresent("name=nextStep");
test.endStep();
test.endTransaction();
The problem I am facing is that click does not return immediately and waits for the overlay to completely load. However I want to stop as soon as desired element is visible. How can I ensure that selenium.click return immediately instead of waiting till entire page is loaded.
you can try using this Java method,
public WebElement waitForVisibilityOfElementLocatedBy(final By locator) {
return waitFor(visibilityOfElementLocated(locator));
}
public static ExpectedCondition<WebElement> visibilityOfElementLocated(final By locator) {
return new ExpectedCondition<WebElement>() {
public WebElement apply(WebDriver driver) {
try {
return ExpectedConditions.elementIfVisible(ExpectedConditions.findElement(locator, driver));
} catch (StaleElementReferenceException var2) {
return null;
}
}
public String toString() {
return "visibility of element located by " + locator;
}
};
}`

Redirect to a page after a pop up opens

I am trying to redirect a web page after a condition is returned as true but I can't seem to get it work. In theory this should, shouldn't it. What am I missing, is it even possible!
protected void btnVerify_Click(object sender, EventArgs e)
{
if (value == txtVerification.Text || txtVerification.Text == "****")
{
//defines a bool to tell if the popup window has been shown, this will only ever return true
bool PopupShown = doRedirect();
if(PopupShown)
{
Response.Redirect("somewebpage.aspx");
}
}
else
{
lblVerificationFailed.Visible = true;
}
}
//Opens the popup window to fire off the download and returns true
bool doRedirect()
{
string url = "GetDocs.aspx";
string s = "window.open('" + url + "', 'GetDocs', 'height=150,width=300,left=100,top=30,resizable=No,scrollbars=No,toolbar=no,menubar=no,location=no,directories=no, status=No');";
ClientScript.RegisterStartupScript(this.GetType(), "script", s, true);
return true;
}
You are trying to do in the server things that can be much more easily done on the client side.
You're using a server event to catch the click of a button on your view, launch a client popup and later redirect your page execution.
Try with something like this on javascript:
var btnVerify = document.getElementById("btnVerify");
btnVerify.addEventListener("click", function() {
window.open('GetDocs.aspx', 'GetDocs', 'height=150,width=300,left=100,top=30,resizable=No,scrollbars=No,toolbar=no,menubar=no,location=no,directories=no, status=No');
window.location.href = "somewebpage.aspx";
});
Sussed it, if I use window.location.replace instead of window.location it works exactly like I want it to. Many thanks all :)

cefsharp execute javascript

I want to execute JavaScript code by using CefSharp in Windows Forms, but it does not work. The code is as following, and the message test is not shown. Did I miss something?
var browser = new ChromiumWebBrowser("http://localhost:50056/simple.aspx");
browser.Name = "Simple Page";
browser.Dock = DockStyle.Fill;
this.Controls.Add(browser);
browser.ExecuteScriptAsync("alert('test');");
You must wait for the browser to have sufficiently loaded before executing JavaScript. It's tempting to start trying to access the DOM in OnFrameLoadStart, whilst the V8Context will have been created and you will be able to execute a script the DOM will not have finished loading. If you need to access the DOM at its earliest possible point, subscribe to DOMContentLoaded.
Some examples of executing JavaScript are below.
browser.RenderProcessMessageHandler = new RenderProcessMessageHandler();
public class RenderProcessMessageHandler : IRenderProcessMessageHandler
{
// Wait for the underlying JavaScript Context to be created. This is only called for the main frame.
// If the page has no JavaScript, no context will be created.
void IRenderProcessMessageHandler.OnContextCreated(IWebBrowser browserControl, IBrowser browser, IFrame frame)
{
const string script = "document.addEventListener('DOMContentLoaded', function(){ alert('DomLoaded'); });";
frame.ExecuteJavaScriptAsync(script);
}
}
//Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
browser.LoadingStateChanged += (sender, args) =>
{
//Wait for the Page to finish loading
if (args.IsLoading == false)
{
browser.ExecuteJavaScriptAsync("alert('All Resources Have Loaded');");
}
}
//Wait for the MainFrame to finish loading
browser.FrameLoadEnd += (sender, args) =>
{
//Wait for the MainFrame to finish loading
if(args.Frame.IsMain)
{
args.Frame.ExecuteJavaScriptAsync("alert('MainFrame finished loading');");
}
};
I think, in the case of calling a JavaScript function that exists inside HTML, and passing input arguments, one can simply use the Browser.LoadingStateChanged event in the MainWindow constructor to make sure loading is initiated. This event will be called after the Browser_Loaded, where the HTML file is declared. Following is an example of the code:
public MainWindow()
{
InitializeComponent();
//Wait for the page to finish loading (all resources will have been loaded, rendering is likely still happening)
Browser.LoadingStateChanged += (sender, args) =>
{
//Wait for the Page to finish loading
if (args.IsLoading == false)
{
Browser.ExecuteScriptAsync("JavaScripFunctionName1", new object[] { arg1, arg2});
}
};
}
private void Browser_Loaded(object sender, RoutedEventArgs e)
{
Browser.LoadHtml(File.ReadAllText(GetFilePath("YourHTMLFileName.html")));
}
However, if you want to execute the JavaScript code and get results, you should use:
var result = await Browser.EvaluateScriptAsync("JavaScripFunctionName2", new object[] { });
MessageBox.Show(result.Result.ToString());
In HTML:
<html>
<body>
<script>
function JavaScripFunctionName1(arg1, arg2)
{
// something here
}
function JavaScripFunctionName2()
{
// something here
return result;
}
</script>
</body>
</html>

Categories

Resources