Using RegisterClientScriptBlock to call JavaScript function from WebControl - javascript

I am creating a website using ASP.
I have a web control with an SVG image embedded on it.
<embed id="InletsComponent" class="InletsComponent" src="../images/svg/Inlets.svg" type="image/svg+xml" width="430px" height="200"px/>
On the web control I also have a button.
<input id="Button3" type="button" value="3 into 2" onclick="return ConfigureInlets()" />
The javascript function is:
function ConfigureInlets() {
document.querySelector(".InletsComponent").getSVGDocument().querySelector(".InletsComponentImage").getElementById("I1IN").setAttribute("visibility", "visible");
return;
}
Which basically makes one of the svg elements visible.
The above code works fine.
I now want to extend the code so that instead of the button calling the function I can call the function from the server side. (the reason for this isn't obvious from the example, but basically I want to show and hide svg elements based on a number of checkbox states. It is easier to process all this on the server side and then call the javascript to update the image on the client.).
I have added a RegisterClientScriptBlock to my server side code
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Key", "ConfigureInlets()", true);
The javascript function is being called, but I am getting the following error:
Microsoft JScript runtime error: Unable to get value of the property 'getSVGDocument': object is null or undefined
I believe that this function is being called at a different level to when the button press is calling it. i.e it is being called at the page level and not the web control level. But I am not really sure how to fix it.

try to use jquery to run this function when the document is ready
this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "Key", "$(function () {ConfigureInlets()});", true);
or use RegisterStartupScript instead of RegisterClientScriptBlock

Related

React/javascript component to send data back to aspx

I've a legacy ASP.NET application, which I'm trying to modernize. I've a page
MyPage.aspx, and its codebehind MyPage.aspx.cs
I've replaced a custom user control (which does a fileupload) with a custom react component. The react component is working as expected. The old ascx usercontrol had an event handler which is defined in 'MyPage.aspx.cs'as follows.
protected void asyncFile_FileUploaded(object sender, FileUploadedEventArgs e)
//logic to set the uploaded file's name etc for saving.
}
Nowthat the custom control is replaced with an empty DIV, where the react component is being mounted, I'm left with no option to call my C# logic in the 'MyPage.aspx.cs' codebehind file.
I've created a 'CreateProperty.aspx.js' file which is responsible of initializing my react component inside the .aspx page, and below is the contents of this file.
$(document).ready(function () {
if ($('#Myupload').length) {
ReactDOM.render(
<Upload id="pictureupload2"
onChange={onChange}
setBusyState={onBusy}
onUploadSucceeded={onUploadSucceeded}
/>,
document.getElementById("Myupload")
);
}
});
function onChange(e) {
console.log(e);
}
function onBusy(e) {
console.log(e);
}
function onUploadSucceeded(e) {
console.log(e);
}
Once the react component has done the uploading, it calls the function onUploadSucceeded() with my required parameters. But how will I pass that value back to my MyPage.aspx.cs file ?
Please help.
Drop in a standard asp.net button on the form.
Move the code you have/had for the previous event into that button code stub
eg:
protected void asyncFile_FileUploaded(object sender, FileUploadedEventArgs e)
//logic to set the uploaded file's name etc for saving.
}
So, move the above code to the button (style="display:none) to hide it.
AND OF COURSE don't copy the event stub code!!!.
Now, in your js function, do whatever and simply "click" on that button.
The bonus here is you get the badly needed post back when the client side js/ajax runs.
So, you have this:
function onUploadSucceeded(e) {
console.log(e);
document.getElementById('<%= btnOkUpLoad.ClientID %>').click();
So, the above is nice. I mean you could do a js __DoPostBack(); in js, but then you have to pass some parameters, and then client side in the on-load page event, detect the parameters (a pain to wrire up).
So, anytime I want to run code behind from js? Just drop in a asp button, write the code stub for that button, and then client side, use the above ".click()" to run that code. As noted, in MOST cases you want a post back anyway - which is what a asp.net button does for you.
Edit: now I said we want a post back in most cases? Well, I mean when we are all said and done - and thus this button click makes sense. We certainly don't want needless post backs - but when you do, and when you want to run+call a code stub, the this button trick is nice. Just use style="display:none" to hide it from view - but js code can still use the .click() to run (click) the button for you))

Trigger Apache Velocity #set Parameter using a button (HTML / JS)

Is it possible to trigger a Velocity Template Language #set value to parameter via a button?
I am trying to combine HTML, JS and Velocity doing the following:
#set($ld=$pageParameters.Work_Item_Link_Direction.values)
<button id="demo2">up</button>
<script>
document.getElementById('demo2').onclick = function() {
#set( $ld = "up" )
alert("button2 was clicked");
};
</script>
The part, however, which doesn't work in this code is:
#set ( $ld = "up")
as it isn't pure JavaScript.
Any hints or ideas how I can combine anyway this "#set value to parameter" as function onclick to the button? I am working inside the application Polarion ALM.
Or is there any other approach how I can set a value to a (page) parameter using velocity and using a Button?
There is a little misconception, here:
the Velocity Template Language code is evaluated at the time the page is sent by the HTTP server, on the server itself.
the Javascript code is evaluated once the page is loaded, in the browser.
So what you ask for doesn't really make sense.
What you can do, however, is trigger an ajax call from inside your javascript handler, which can set some value inside the session, return some value to the success ajax handler, etc.

Attaching a callback to html generated by JSF - Primefaces

I've got a Primefaces command button that I need to add a callback to in jQuery on document.ready. Basically what I've been trying to do is get a reference to the existing function and then call it in a new function that I wrote:
var existingFunction = jQuery("[id~='submit']").live("click");
jQuery("[id~='submit']").live("click", function(){
existingFunction();
alert('test');
updateControlPanel(buildControlPanelUrl(getUrlVars()));
});
It seems simple enough to me but for some reason this will not work. When I load the page and click the submit button it doesn't even reach the alert.
I've checked the error console and found that it's throwing the following errors:
((f.event.special[s.origType] || {}).handle || s.handler).apply is not a function
There is existing jQuery functions on the page that I did not write but I'd like to make sure this error is not related to the way I'm approaching this.
I'm using tomcat 6 with an older version of JQuery (1.3 or 1.4 ).
Thanks and let me know if you guys need any more info.
Edit
I've put up an example of what I'm trying to do on JS Fiddle: http://jsfiddle.net/anSXH/2/
Here is some further clarification:
I've built the button as a project in JSF 2.0 (MyFaces) using the latest Primefaces component library. I've then taken that button and embedded it into an existing web page. The button submits the form and then calls a JavaScript function to show the result on the page after an ajax request is complete. This all works when I embed the button onto the page but I now need to update something on the client side after the button calls the function. That's why I'm looking at adding a callback to the existing onclick function.
As a side note, because I'm using Primefaces I can attach a JavaScript function to run after the ajax request is complete. My plan B is to try and access this function and somehow override it.
Edit part 2
Here is the generated control from primefaces:
<button
id="topsaveform:submittop"
name="topsaveform:submittop"
class="ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
onclick="PrimeFaces.ab({source:'topsaveform:submittop',process:'topsaveform OEIMeasurementsTable',update:'errorMessages submittedPopup',onstart:function(cfg){jQuery('#loadingBar').show('fast');;},oncomplete:function(xhr,status,args){postSubmit();;}});return false;"
type="submit">
<span class="ui-button-text">Save</span>
</button>
Did you try making the original function die (ref)?
jQuery("[id~='submit']").die("click");
jQuery("[id~='submit']").live("click", function(){
alert('test');
updateControlPanel(buildControlPanelUrl(getUrlVars()));
});
The problem was that I was trying to do this with a primefaces button. When I switched to a standard JSF button I was able to affix the function to it no problem.

Server side JavaScript action

I coded a chat script using AJAX.NET. For every button click I am using the following sample of code in which I am using OnClientClick function to scroll down on every button click i.e. update.
<asp:Button ID="btn_msg" runat="server" Text="Submit" OnClick="btn_msg_Click" OnClientClick="scrolldown('div1')" />
This results fine on the page I am working but in the receiver side scroll bar is not getting down on update. I guess changing the option OnClientClick to some server action will help. I tried adding OnClick="btn_msg_Click; scrolldown('div1');" but this is not working. Is there any alternate way to fulfill my action.
At first glance, I believe Anton is correct. The reason you are seeing this behavior is the order in which everythings runs. The client script runs first. Then the server script. The server script causes a postback( or even via an update panel ), causing it to render the html again, losing the scroll bar position.
Anton's code causes the scrolldown function to run once the ajax postback is complete.
A side note:
If I were doing this, I'd remove the AJAX.NET completely and switch to jquery. You have a lot more control over this kind of stuff.
You need to hook on the endCallback event to scrolldown.
The moment you try to scroll down content is not yet delivered.
Try it this way:
<body onload=”load()”>
<script>
function EndRequestHandler()
{
scrolldown('div1');
}
function load()
{
Sys.WebForms.PageRequestManager.getInstance().add_endRequest(EndRequestHandler);
}
</script>

Server-Side callback function to solve JS-CF execution order dependency?

I would like to call a form as pop-up window (a form with some input fields and a submit button) and then read the user selected results from the session. The problem is that the mixing of JS code (pop-up window) with CF (server-side) code, as is expected, causes the process to output the session variable before the process updates it. For better understanding, hereunder is the scenario together with some relevant code snippets:
Scenario:
1. User calls ShowForm(..)
2. ShowForm(..) displays a pop-up window and waits for the user
to submit his selection
3. The result gets stored in the session
4. The function returns the user-submitted result
form.cfc
<cffunction name="ShowForm" access="public" output="true" returntype="string">
<script>
window.showModalDialog('formpage.cfm',null,"dialogHeight=400px,dialogLeft=150px");
</script>
<cfreturn session.form_result> <!--- #toFix: The return of form_result is happening before the actual form_result is set. --->
</cffunction>
formpage.cfm
<cfajaxproxy cfc="components.sess_mgr" jsclassname="JSMaskProxy">
<script>
function submitSelection(formObj)
{
for (i=0; i<intSelValue.length; i++)
result.push(intSelValue[i]);
var instCfProxy = new JSMaskProxy();
instCfProxy.setToSession(result); // updates session.form_result
//window.returnValue=result;
window.close();
}
</script>
<form name="frmDtls">
<td align="center"><input type="button" id="selectButton" name="selectButton" onClick="submitSelection(details);">
</form>
What's your take on this? How to solve this problem?
ColdFusion.navigate(..) function can have a callback function and an error handler but the thing is that the callback function can only be a client-side function. If the function could be a CF function or maybe a server-side page I think that would solve this dependency problem.
Something on the side, ideally I would love to read the value from window.showModalDialog rather than reading it from the session, but this is just a sketch and the main point here is how to overcome this JS-CF intermingling problem.
Rather than using window.showModalDialog use something like cfwindow, jQuery dialog or an extjs window. All of these have some form of callback or event listener. cfwindow has a onHide function, jQuery dialog has a close option to which a function can be assigned, ext.window has onHide, as well as event listeners.
All of these will allow you to open a new "window" and run some function when the window is hidden or closed. Those functions should all have access to anything from the window as well as being able to access the main window.
Ray Camden has a cfwindow example : http://www.coldfusionjedi.com/index.cfm/2008/9/26/Ask-a-Jedi-Another-CFWINDOW-Example
jQuery dialog has an example of what you're after : http://jqueryui.com/demos/dialog/#modal-form
Sencha's Ext.Window examples show passing values to the main window when a dialog is closed : http://dev.sencha.com/deploy/dev/examples/message-box/msg-box.html
Plenty of options there. I hope they help.
Problem solved!
The solution adopted is based on Stephen Moretti idea which is that of replacing window.showModalDialog with cfwindow call. This alone does not solve the problem. However, I worked when replacing the script tag with cfscript, and then inside the cfscript I simply do a server-side redirection to the page with cfwindow tag.

Categories