I have a page that includes javascript which I only want to run under certain conditions. To do this I have placed the scripts into an asp:placeholder
This actually seems to work but when I run a debug on the page I get the following warning.
Element 'placeholder' is not a known element. This can occur if there is a compilation error in the Web site, or the web.config file is missing.
If I move the placeholders into the body of the page the warning goes, but that means I'm left with scripts in the body which I also want to avoid. Does anyone have any hints on the best practice for this scenario?? thanks
Sub Page_Load(ByVal Sender as Object, ByVal E as EventArgs)
dim lt as new Literal()
lt.text = "<script type='text/javascript' src='scripts/pageLoadAnimations.js'></scr" & "ipt>"
me.Header.Controls.Add(lt)
End Sub
You can include JS file straight from code behind:
If (some condition is true) Then
Page.ClientScript.RegisterClientScriptInclude("jQuery", "jquery-version.js")
End If
A couple of ways which fit your needs are:
Firstly, you could change your <head> tag to <head id="header" runat="server"> then this allows you to dynamically add anything into it, e.g.
dim lt as new Literal()
lt.text = "<script type='text/javascript' src='pathtojavascriptfile'></script>"
me.Header.Controls.Add(lt)
Or you could create a Public string on your page, then stick the javascript in this.
Public _JS as string
Page_Load
_JS = "alert('here');" ' Or what ever your javascript is
ASPX Page
<head>
<script type="text/javascript" src="jquery-version.js"></script>
<script type="text/javascript">
$().ready(function(){
<%=(me._JS) %>
});
</script>
</head>
You might consider looking into the ClientScriptManager. This will allow you to inject scripts into the header properly using whatever conditions you require.
Including Custom Client Script in ASP.NET Pages
ClientScriptManager Class
Related
I am trying to get CKEditor.NET to insert some text into my CKEditor when the page loads.
Private Sub CKEditor_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles myCKEditor.Load
Dim insertScript As String
insertScript = "<script type=""text/javascript"">window.CKEDITOR.instances.myWidget_myCKEditor.insertText(""test"");</script>"
Dim cManager As ClientScriptManager = Parent.Page.ClientScript
cManager.RegisterStartupScript(Me.GetType, "insertText", insertScript)
End Sub
My page is organized as follows:
myPage (aspx)
myWidget (ascx)
myCKEditor (from an assembly)
I am getting the following error:
TypeError: Cannot read property 'instances' of undefined
It appears that CKEDITOR is not around when this is called. If I open up the JS console and run the insertScript it works as desired.
I have tried attaching this routine to MyBase.Load and Me.Load as well to no avail, and even tried using window.Load = insertScript, all of which produce the same error.
I noticed that no matter what I do, the last thing in the source is the script that initializes CKEditor, ie
....
<script type="text/javascript">window.CKEDITOR.instances.myWidget_myCKEditor.insertText("test");</script>
<script type="text/javascript">
//<![CDATA[
window.CKEDITOR_BASEPATH = '/ckeditor/';
//]]>
</script>
<script src="/ckeditor/ckeditor.js?t=C6HH5UF" type="text/javascript"></script>
<script type="text/javascript">
//<![CDATA[
var CKEditor_Controls=[],CKEditor_Init=[];function CKEditor_TextBoxEncode(d,e){var f;if(typeof CKEDITOR=='undefined'||typeof CKEDITOR.instances[d]=='undefined'){f=document.getElementById(d);if(f)f.value=f.value.replace(/</g,'<').replace(/>/g,'>');}else{var g=CKEDITOR.instances[d];if(e&&(typeof Page_BlockSubmit=='undefined'||!Page_BlockSubmit)){g.destroy();f=document.getElementById(d);if(f)f.style.visibility='hidden';}else g.updateElement();}};(function(){if(typeof CKEDITOR!='undefined'){var d=document.getElementById('myWidget_myCKEditor');if(d)d.style.visibility='hidden';}var e=function(){var f=CKEditor_Controls,g=CKEditor_Init,h=window.pageLoad,i=function(){for(var j=f.length;j--;){var k=document.getElementById(f[j]);if(k&&k.value&&(k.value.indexOf('<')==-1||k.value.indexOf('>')==-1))k.value=k.value.replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&');}if(typeof CKEDITOR!='undefined')for(var j=0;j<g.length;j++)g[j].call(this);};window.pageLoad=function(j,k){if(k.get_isPartialLoad())setTimeout(i,0);if(h&&typeof h=='function')h.call(this,j,k);};if(typeof Page_ClientValidate=='function'&&typeof CKEDITOR!='undefined')Page_ClientValidate=CKEDITOR.tools.override(Page_ClientValidate,function(j){return function(){for(var k in CKEDITOR.instances){if(document.getElementById(k))CKEDITOR.instances[k].updateElement();}return j.apply(this,arguments);};});setTimeout(i,0);};if(typeof Sys!='undefined'&&typeof Sys.Application!='undefined')Sys.Application.add_load(e);if(window.addEventListener)window.addEventListener('load',e,false);else if(window.attachEvent)window.attachEvent('onload',e);})();CKEditor_Controls.push('myWidget_myCKEditor');
CKEditor_Init.push(function(){if(typeof CKEDITOR.instances['myWidget_myCKEditor']!='undefined' || !document.getElementById('myWidget_myCKEditor')) return;CKEDITOR.replace('myWidget_myCKEditor',{"htmlEncodeOutput" : true}); });
//]]>
</script>
</form>
....
All the evidence suggests that I am invoking the startup script at the wrong time, but I don't know when the "right time" to invoke it is.
Yoy can use jquery windows.ready function as below
insertScript = "<script type=""text/javascript""> <script language="javascript">
$(document).ready(function() {
window.CKEDITOR.instances.myWidget_myCKEditor.insertText('test');
})
})
</script> ";
Dim cManager As ClientScriptManager = Parent.Page.ClientScript
cManager.RegisterStartupScript(Me.GetType, "insertText", insertScript)
It will make sure your javascript fires only when document get ready and not b4 that.
Kind of a cop-out, but I ended up loading what I needed to insert on the page load and defining the script in the .ascx file.
In my myWidget.ascx:
<script type="text/javascript">
function ddChange(obj) {
window.CKEDITOR.instances.myWidget_myCKEditor.insertText(obj.value);
document.getElementById("myWidget_myCannedPicker").selectedIndex = 0;
}
</script>
...
<asp:DropDownList ID="myCannedPicker" Width="400" runat="server" AutoPostBack="false" OnChange="ddChange(this)" /></span></td>
In myWidget.ascx.vb:
Private Sub fillInitialValues()
...
myCannedPicker.DataSource = dt
myCannedPicker.DataValueField = "msg_text"
myCannedPicker.DataTextField = "msg_name"
myCannedPicker.DataBind()
myCannedPicker.Items.Insert(0, New ListItem("Please make a selection:", "0"))
End Sub
Doesn't really answer to the original question, but it was a suitable workaround in my case.
How do I register a Javascript variable on the server side (backend) and access it on the client side (Javascript file), without a hidden field, Literal, etc.?
You can use the RegisterClientScriptBlock-Function from the Page's ClientScriptManager.
Page.ClientScript.RegisterClientScriptBlock(Page.GetType, "initMyClientVariable", "var myClientVariable=null;", True)
EDIT: according to your new informations, that you want to register a client array, use ClientScriptManager's RegisterArrayDeclaration Method.
VB.Net example:
Dim myArrayValue As String = """1"", ""2"", ""text"""
Page.ClientScript.RegisterArrayDeclaration("myClientArray", myArrayValue)
According to the new information in my comments that you need access to that variable from an external js-file: you should pass the js-array as argument to the function in the js-file. For example:
callFunctionInJsFile(checkBoxes);
You can put the following code in .aspx file ...
<script type="text/javascript" >
var date1 = "<%: DateTime.Now %>";
var date2 = "<%= DateTime.Now %>";
</script>
<%: %> works under ASP.NET 4
You can put a literal in the xml portion of the code and assign that literal some text:
myLiteral.Text = "<script language=\"javascript\">var myVar = 24;</script>";
This makes myVar globally available on the client side once it's rendered. You can also use the ClientScriptManager object to use Asp.Net to inject scripts and variables.
First place an <asp:Literal ID="Literal1" runat="server"></asp:Literal> tag in the <head> of your .aspx file. Then in the server side code in your .aspx.cs file, do something like Literal1.Text = "<script type=\"text/javascript\">var timer = 3600</script>" and you've got yout javascript variable called timer.
That's it. Have fun!
calling a js function using onclick...
onclick="SubmitAge(66, 'ctl00_MainContent_arTo_upAgeRange')"
function just calls an updatePanel from the client... but its saying object expected at the onclick= part!!!
here is the function, is there anything wrong with the code?
function SubmitAge(age, UpdatePanelID) {
$get('HiddenAge').value = age;
__doPostBack(UpdatePanelID);
}
EDIT: THE SUBMITAGE FUNCTION IS INSIDE A .JS FILE (AGERANGE.JS) AND ONLY WHEN MOVED HERE DOES IT STOP WORKING: HERE IS THE LINKING METHOD/HEADERS FROM THE ASCX USERCONTROL INWHICH IT IS ALL CONTAINED...
%# Control Language="VB" ClassName="AgeRange" %
%# Register Assembly="AjaxControlToolkit" Namespace="AjaxControlToolkit" TagPrefix="AjaxCT" %
script src="AgeRange.js" type="text/javascript" /script
(arrow tags removed here as it wont display, hint: stackoverflow!!!)
im printing it like this from the server...
Public Sub AppendToSB(ByRef sb As StringBuilder, ByVal CurNo As Byte, Optional ByVal clickedNo As Byte = 0)
Dim sConfirmClick = ""
If clickedNo = CurNo Then ' maybe dont make it clickable...
sConfirmClick = "return confirm('The number " & CurNo.ToString & " is already selected, are you sure you want to select it again?');"
End If
sb.Append("<a href=""#"" onclick=""" & sConfirmClick & "SubmitAge(" & CurNo.ToString & ", '" & upAgeRange.ClientID &
"')"" runat=""server"">" & CurNo.ToString & "</a>")
End Sub
Complete rewrite of my post after several clarifications:
The problem is that the ASPX page is referencing an ASCX user control that is located in a different folder. That ASCX control has an HTML <script> tag that is using a relative path to the JS file.
The solution is to correctly resolve the URL to the JS file by using some extra code:
<script src="<%= ResolveClientUrl("MyScriptLibrary.js") %>" type="text/javascript">
</script>
To prevent the script file from being referenced multiple times I recommend using the approaches specified in this other post:
ASP.NET dynamically insert code into head
Here's what it looks like in the user control's code:
// Register a script reference:
Page.ClientScript.RegisterClientScriptInclude(GetType(), "myLibraryScript", "~/Scripts/MyScriptLibrary.js");
here is how i decided to do it, ResolveClientURL is important, static link will not always work, also the if check will prevent the script being added several times in one page if you use the control multiple times on same page...
If Not Page.ClientScript.IsClientScriptIncludeRegistered("AgeRangeJS") Then ' no point in registering it twice!
' AND its registered in the header, where it should be, not two copies in the body :)
Page.ClientScript.RegisterClientScriptInclude("AgeRangeJS", ResolveClientUrl("AgeRange.js")) ' ResolveClientUrl("AgeRange.js")
End If
How do you add Javascript file programmatically to the user control?
I want the user control to be a complete package - ie I don't want to have to add javascript that's related to the user control on the page where it's used, when I can do it inside the control itself.
Since there is no Page object in the user control, how would you do it?
In the Page_Load method of control.ascx.cs file:
LiteralControl jsResource = new LiteralControl();
jsResource.Text = "<script type=\"text/javascript\" src=\"js/mini-template-control.js\"></script>";
Page.Header.Controls.Add(jsResource);
HtmlLink stylesLink = new HtmlLink();
stylesLink.Attributes["rel"] = "stylesheet";
stylesLink.Attributes["type"] = "text/css";
stylesLink.Href = "css/mini-template-control.css";
Page.Header.Controls.Add(stylesLink);
This will load css and Javascript into the head tag of the main page, just make sure that the head has runat="server".
You can register client script includes using the ClientScriptManager.
Page is accessible through the Control.Page property.
Page.ClientScript.RegisterClientScriptInclude (
typeof ( MyControl ), "includeme.js", "js/includeme.js" );
EDIT: Sorry, for a total "complete package", its possible using scripts as Embedded Resources,
and aquire dynamic URL's through the WebResource.axd handler.
If this is not considered totally complete, then i guess it could be put in App_LocalResources, but it never gonna be just one file,
unless the code and script is inline.
The same as gnomixa's response, only a bit cleaner:
HtmlGenericControl js = new HtmlGenericControl("script");
js.Attributes["type"] = "text/javascript";
js.Attributes["src"] = "jscript/formfunctions.js";
Page.Header.Controls.Add(js);
from http://www.aspdotnetfaq.com/Faq/How-to-Programmatically-add-JavaScript-File-to-Asp-Net-page.aspx
In my site I Place all needed scripts and styles to placeHolder
<asp:placeHolder runat="Server" ID="phHead">
<script src="/header/widget/script.js" type="text/javascript"></script>
<link href="/header/widget/style.css" rel="stylesheet" type="text/css" />
</asp:placeHolder>
and
Private Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Page.Header.Controls.Add(phHead)
End Sub
Good question!
A UserControl should be a single package without any dependency on a JavaScript or a CSS file. You will need to make the JS and CSS files as embedded resources. Right click properties and set build action to embedded resources. Then you need to inject the JavaScript and CSS files as WebResources.
Here is one article that I wrote yesterday which talks about the same scenario:
http://highoncoding.com/Articles/502_Creating_RadioButton_Validation_Using_Custom_Validator.aspx
I generally do it when rendering the HTML for the control and depending on whether it's a library injection or an instance injection I use the Items collection to specify whether or not I have already produced the code for a control of this type during the current request using a unique identifier.
Something to the effect of:
protected override void Render(HtmlTextWriter writer)
{
base.Render(writer);
//Check if the Object Script has already been rendered during this request.
if (!Context.Items.Contains("xxx"))
{
//Specify that the Object Script has been rendered during this request.
Context.Items.Add("xxx", string.Empty);
//Write the script to the page via the control
writer.Write([libraryinjection]);
}
//Write the script that instantiates a new instance for this control
writer.Write([instanceinjection]);
}
If you have the text of the actual javascript in your .CS file, you can call Page.ClientScript.RegisterClientScriptBlock.
The following assumes that "GetScript()" returns the actual javascript you want added to the rendered control.
Page.ClientScript.RegisterClientScriptBlock(GetType(), "controlScriptName", GetScript());
I found this to be a more elegant way to fix-link to your javascript.
In your .ascx, link to your script files the following way:
<script src='<%= ResolveClientUrl("~/Scripts/jquery-1.7.1.min.js") %>' type="text/javascript"></script>
<script src='<%= ResolveClientUrl("~/Scripts/jquery.maskedinput-1.3.min.js") %>' type="text/javascript"></script>
That way, no matter which subfolder/page you add your user control to, the link to your scripts will always be correctly resolved.
Started to look at the Treeview control.
Is there anyway to tie the Tree View control into a Directory structure on the Web Server using Visual basic?
I have a lot of legacy files, which are updated and added often. Obviously I could code the structure in XML but this would be laborious and hard to train out to the end user.
I guess it would be a dynamic creation of an XML file perhaps?
Here's an elementary sample that I created awhile ago when learning to play with the TreeView. I have now converted the code to VB.NET using an online converter for your benefit.
It recursively walks the directory tree starting from the root of the virtual directory and creates nodes for each sub-directory or file encountered. I think this is exactly what you needed.
For visual separation, I had used icons to differentiate files from folders (folder.gif and file.gif). You can remove that parameter if you want.
Complete ASPX follows (You can paste it into a new page and it should run):
<%# Page Language="VB" %>
<%# Import Namespace="System.IO" %>
<script runat="server">
Protected Sub Page_Load(ByVal sender As Object, ByVal e As EventArgs)
If Not Page.IsPostBack Then
Dim rootDir As New DirectoryInfo(Server.MapPath("~/"))
' Enter the RecurseNodes function to recursively walk the directory tree.
Dim RootNode As TreeNode = RecurseNodes(rootDir)
' Add this Node hierarchy to the TreeNode control.
Treeview1.Nodes.Add(RootNode)
End If
End Sub
Private Function RecurseNodes(ByVal thisDir As DirectoryInfo) As TreeNode
Dim thisDirNode As New TreeNode(thisDir.Name, Nothing, "Images/folder.gif")
' Get all the subdirectories in this Directory.
Dim subDirs As DirectoryInfo() = thisDir.GetDirectories()
For Each subDir As DirectoryInfo In subDirs
thisDirNode.ChildNodes.Add(RecurseNodes(subDir))
Next
' Now get the files in this Directory.
Dim files As FileInfo() = thisDir.GetFiles()
For Each file As FileInfo In files
Dim thisFileNode As New TreeNode(file.Name, Nothing, "Images/file.gif")
thisDirNode.ChildNodes.Add(thisFileNode)
Next
Return thisDirNode
End Function
</script>
<html>
<head>
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<asp:treeview ID="Treeview1" runat="server"></asp:treeview>
</form>
</body>
</html>
A custom sitemap provider is a good bet.
There is a good article on 4guys title "Examining ASP.NET 2.0's Site Navigation - Part 4 "