In my website I'm using the standard ASP.NET menu control. I already got so far as to write a custom control adapter to get rid of the rather tacky html output that is generated by the default control adapter.
One thing keeps buggering me though. Somehow ASP.NET is generating extra javascript that I don't want nor need for my menu controls, since I won't be using any of the dynamic features in the control. I replaced the control adapter, so it doesn't generate compatible HTML for that.
Anyone got an idea how I can prevent ASP.NET from generating the extra javascript for the menu control?
This problem cropped up for me after upgraded to ASP.net 4.0 with the installation of vs 2010. The fix is to either force the menu to render as a table or to turn off the new CSS/javascript "features" that 4.0 adds. Settings the menu's RenderingMode attribute to "Table" fixed this problem for me even though I use a Menu Adapter to render the control with lists.
<asp:Menu ID="mnuStuff" runat="server" RenderingMode="Table">
...
</asp:Menu>
You can do this site wide setting controlRenderingCompatibilityVersion to 3.5 in the web.config:
<system.web>
<pages controlRenderingCompatibilityVersion="3.5"/>
</system.web>
This will eliminate the rendering of inline javascript that asp injects in the base of the page.
If you prefer to stick with ASP.Net 4.0 control rendering you can create a custom menu (derived from System.Web.UI.WebControls.Menu) and replace the OnPreRender:
public class MyCustomMenu : Menu
{
protected override void OnPreRender(EventArgs e)
{
// Don't call base OnPreRender
//base.OnPreRender(e);
}
}
That did the trick.
An alternative way to get rid of the menu startup script is to call RegisterStartup script method before the Menu PreRender event, using the same script key, and outputting dummy (or empty) script.
This relies on internal implementation details of the Menu Type discovered using Reflector, so is somewhat fragile.
For example, a static class that looks something like:
static MenuHelper
{
private static Type _rendererType =
typeof(Menu).Assembly.GetType(
typeof(Menu).FullName + "+MenuRendererStandards"
);
public static void RemoveMenuScript(Menu menu)
{
string dummyScript = "<!-- Removed Menu Startup script -->";
string key = "_registerMenu_" + menu.ClientID;
ScriptManager.RegisterStartupScript(menu, _rendererType, key, dummyScript, false);
}
}
You then just need to make sure you call MenuHelper.RemoveMenuScript(menu) before the menu's PreRender event.
The OP is using an Adapter so Tim Santeford's answer is better in his situation. But if you want to render a static menu as a list without the startup code, and without the effort of writing an adapter, this might be an alternative.
<script type="text/javascript">
Sys.WebForms.Menu = "";
</script>
it works..
use it in aspx page
I just plan to ask about a similar question after 2 hours of search and have no luck.
What I want is to use the jquery superfish plugin as I want its animation for smooth looking. And with the ASP.NET generated javascript, the superfish just won't work.
And finally I try to set the ASP.NET Menu's control's attribute Enabled = false
and the outcoming source becomes this:
new Sys.WebForms.Menu({ element: 'mysitemeun', disappearAfter: 500, orientation: 'horizontal', tabIndex: 0, disabled: **true** });
After tracing the code, setting it disabled still have some style changes in the Menu but it will not add event to the MenuItem. And the superfish's animation works now.
if (!this.container.disabled) {
Sys.WebForms.Menu._domHelper.addEvent(this.element, 'mouseover', Sys.WebForms.MenuItem._onmouseover);
Sys.WebForms.Menu._domHelper.addEvent(this.element, 'mouseout', Sys.WebForms.MenuItem._onmouseout);
}
Related
I have performance issue on website, because of too long viewstate in source code. on some pages it's size is more than 15-20kb. Which is increasing the load time on browser.
Is there any way to disable viewstate partially or fully without any harm on other module of website. FYI there is one listview and one form on these example pages. where viewstate is very long.
More Example pages
http://www.pricingindia.in/coupons/ebay-in-coupon-codes-20
http://www.pricingindia.in/coupons/flipkart-coupon-codes-32
You probably want to disable for ViewState for your Page in general, and then only enable ViewState for the controls that need / use it.
See this MSDN page on the Control.ViewStateMode property, it describes how to set that up:
To disable view state for a page and to enable it for a specific
control on the page, set the EnableViewState property of the page and
the control to true, set the ViewStateMode property of the page to
Disabled, and set the ViewStateMode property of the control to
Enabled.
You will need to do some testing to see which controls need / use the ViewState in your specific app. But, basically,
anything that's static, you can disable the ViewState (Buttons, LinkButtons, etc).
Any controls whose state doesn't need to be restored between PostBacks, you can disable ViewState (such as a TextBox in a form that is submitted to the server, and then cleared).
Any controls that need to keep their state between PostBacks, you want to enable Viewstate (this would often be databound controls like GridViews / etc).
Doing this should definitely reduce the load that ViewState is putting on your pages.
Okay, I couldn't leave well enough alone:
Firebug said the following bit of code blocked the site from rendering for about 6 seconds. I thought it was the jsapi (based on info from chrome's tools) but the following returned a "502 Bad Gateway" message meaning that it sat there spinning it's wheels unable to process while preventing your web page from displaying.
I would move the <script .. call to the header, where it belongs. Then I'd move the google.load and google.setOnLoadCallback to the bottom of the web page so it runs last.
Finally I'd figure out exactly why it's failing to work right.
Homework for you: get Firebug loaded into firefox and learn how to use it's Net tools to see where site loading issues are.
<div class="sr_bx1 FL clearfix">
<div class="FL searchbg">
<div id='cse' style='width: 100%;'>Loading</div>
<script src='http://www.google.com/jsapi' type='text/javascript'></script>
<script type='text/javascript'>
google.load('search', '1', { language: 'en', style: google.loader.themes.V2_DEFAULT });
google.setOnLoadCallback(function () {
var customSearchOptions = {};
var orderByOptions = {};
orderByOptions['keys'] = [{ label: 'Relevance', key: '' }, { label: 'Date', key: 'date'}];
customSearchOptions['enableOrderBy'] = true;
customSearchOptions['orderByOptions'] = orderByOptions;
var imageSearchOptions = {};
imageSearchOptions['layout'] = 'google.search.ImageSearch.LAYOUT_POPUP';
customSearchOptions['enableImageSearch'] = true;
customSearchOptions['overlayResults'] = true;
var customSearchControl = new google.search.CustomSearchControl('010882286766777081969:xkox132izzk', customSearchOptions);
customSearchControl.setResultSetSize(google.search.Search.FILTERED_CSE_RESULTSET);
var options = new google.search.DrawOptions();
options.setAutoComplete(true);
customSearchControl.draw('cse', options);
}, true);
</script>
</div>
Using Page Adapter Class, you can solve this problem. I found following solution helpful for ASP.NET Web Application:
view state serialization is handled by an object of type PageStatePersister. (The PageStatePersister class is an abstract class that defines the base-level functionality for serializing view state to some persistent medium.)
Steps:
1) In Your Web Application, Add Folder: App_Browsers
2) In this folder, Add new BrowserFile: ViewStateAdapter.browser
3) Write following code in it:
<browsers>
<browser refID="Default">
<controlAdapters>
<adapter controlType="System.Web.UI.Page" adapterType="ServerSideViewStateAdapter" />
</controlAdapters>
</browser>
</browsers>
4) In Your WebApplication, Add Folder: App_Code
5) In this folder, Add new ClassFile: ServerSideViewStateAdapter.cs
6) Write following code in it:
using System;
using System.Web.UI;
using System.Web.UI.Adapters;
public class ServerSideViewStateAdapter : PageAdapter
{
public override System.Web.UI.PageStatePersister GetStatePersister()
{
return new SessionPageStatePersister(this.Page);
}
}
You can refer this video, it can help you:
https://www.youtube.com/watch?v=36pmFySbXZA
Long story short, dozens of pages use no master page. For a new module I created a master page with a menu control (menu control exists already) so I can get the same look across the six or so pages I'm creating now. Since the content page uses the master page, the Menu control has its name changed to ct100_Menu1 instead of just Menu1. Wouldn't be an issue except someone decided to use the exact name of the control for the CSS that styles the menu, by its exact ID (e.g. CSS is Menu1 a { /* stuff */ }). So the menu won't render properly because I'm using a Master Page and not just copying the code.
I cannot change the CSS code in the menu file as it could break something, so is there any way that I can change the control to not display that pesky ct100 without having to add any tools or mess with creating my own custom control (as I can't replace the Menu.ascx control, although I might be able to modify it to add CSS classes) or is my only choice to either not use a master page or copy the menu CSS into another file and set it properly?
Feel kind of stuck between a rock and a hard place because the code was deliberately written so you cannot use Master Pages and nobody ever went back to change it.
You should set the ClientIdMode to Static. Here's more information from MSDN. Note: This is .NET 4.0 only.
In earlier versions, I would recommend styling off of classes as you can't really control what the name will be everywhere that you use it (as you found out).
If you are on ASP.net 4.0, you can set the ClientID property of the controls.
Otherwise, you're in for a world of hurt as in: Custom Control, ASP.net Literals or JavaScript to change the IDs.
Are you using .NET 4? If so, you can set this on your control:
<asp:SomeControl ClientIDMode="Static" />
Just add the new name to the CSS - without removing the old (since you said that was an issue):
ctl100_Menu1 a,
Menu1 a { /* stuff */ }
If you are using ASP.NET 4.0, you can override the ClientId rendering mode, either per control, or for all controls. For instance:
<my:Menu runat="server" Id="Menu1" ClientIDMode="Static" />
This will enforce that the value "Menu1" is preserved as the client side Id for the element that is rendered. (see here).
What I would recommend though, is apply a CSS class to the menu element, and then adjust the CSS rules around a class. E.g.,:
#Menu1 a {
... to:
#Menu1 a,
div.menu a {
... etc
To "correct" this behavior for your entire web application, look in your web.config for the following tag:
<system.web>
...
<pages ... clientIDMode="*something*">
</pages>
...
</system.web>
Remove the clientIDMode="*something*" property specification. Just take it out.
Yay.
Using .NET 3.5.
How do I programmtically expand/collapse the panes contained within a AJAX accordion control?
My page will have several accordions controls which I want to be able to mass expand/collapse with some buttons.
UPDATE1
My final code solution looks like this:
<script language="javascript">
function collapse_all(flag)
{
if(flag==true)
{
var behavior = $get("<%=Accordion1.ClientID%>").AccordionBehavior;
behavior.set_SelectedIndex(-1);
}
else
{
var behavior = $get("<%=Accordion1.ClientID%>").AccordionBehavior;
behavior.set_SelectedIndex(0);
}
}
</script>
you can find the accourdion control in javascript and call "set_SelectedIndex(-1)"
so (using jquery)
$("#<%=Accordion1.ClientID%>_AccordionExtender").set_SelectedIndex(-1)
if you have a few, you can either do them all discretly or use one of the jquery selectors to find them all, the accordions will have to have been set up to allow all panes to close i believe (RequireOpenedPane = false)
You can't expand them programmatically via you server-side code(VB.NET/C#) because the expansion of the panes is done in the client-side code(JavaScript). If I were you I'd suggest taking a look at the JQuery Libraries and using their show/hide functions to build a custom accordion control to do what you want. JQuery will seem less "WebForm-like" but you'll find it much more flexible than the AJAX Control Toolkit.
If you put the accordion control in an asp.net ajax update panel, you can collapse all panes easily via the codebehind setting the selected index to zero.
I am using the example on the AJAX website for the DropDownExtender. I'm looking to make the target control (the label) have the DropDown image appear always, instead of just when I hover over it.
Is there any way to do this?
This can be done using the following script tag:
<script>
function pageLoad()
{
$find('TextBox1_DropDownExtender')._dropWrapperHoverBehavior_onhover();
$find('TextBox1_DropDownExtender').unhover = VisibleMe;
}
function VisibleMe()
{
$find('TextBox1_DropDownExtender')._dropWrapperHoverBehavior_onhover();
}
</script>
I found this and some other tips at this dot net curry example.
It works but I'd also consider writing a new control based on the drop down extender exposing a property to set the behaviour you want on or off.
Writing a new AJAX control isn't too hard, more fiddly than anything.
I have an ASP.NET server control which relies on JQuery for certain functionality. I've tried to add as a webresource.
My problem is my method of including the jquery file adds it to the body, or the form to be exact:
this.Page.ClientScript.RegisterClientScriptInclude(...)
The alternative to this is to add it as a literal in the head tag:
LiteralControl include = new LiteralControl(jslink);
this.Page.Header.Controls.Add(include);
The problem with this however is any existing code srcs in the head which use JQuery fail, as JQuery is loaded afterwards (ASP.NET adds the literal at the bottom of the control tree).
Is there a practical way of making JQuery an embedded resource, but loaded in the head first? Or should I give up now.
If you want to package up jQuery and embed it inside your own server control you should serve it to the client using the ScriptManager. From the top of my head you have to:
add jQuery.js to your project
under its "Build Action" Property,
make it an Embedded Resource
in the AssemblyInfo.cs for your
control add
[assembly: WebResource("<Your Server Control namespace>.jQuery.js", "application/x-javascript")]
Make your control inherit from
System.Web.UI.ScriptControl (or at
least implement IScriptControl)
Override GetScriptReferences:
protected override IEnumerable<ScriptReference>
GetScriptReferences()
{
return new ScriptReference[] {
new ScriptReference("<Your Server Control namespace>.jQuery.js", this.GetType().Assembly.FullName),
};
}
All of your own client script should be setup inside:
protected override IEnumerable<ScriptDescriptor> GetScriptDescriptors()
Which will then ensure the correct order of dependencies (ie jQuery will be available to your own client script).
Update:
A far easier way of doing it is to simply add the script tag dynamically, in your script and point to the google code hosting. e.g.
function include_dom(script_filename) {
var html_doc = document.getElementsByTagName('head').item(0);
var js = document.createElement('script');
js.setAttribute('language', 'javascript');
js.setAttribute('type', 'text/javascript');
js.setAttribute('src', script_filename);
html_doc.appendChild(js);
return false;
}
include_dom("http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js");
The function is taken from this article
Crecentfresh pushed me in the right direction, I also found
http://en.csharp-online.net/Creating_Custom_ASP.NET_AJAX_Client_Controls—IScriptControl.GetScriptReferences_Method.
My problem still remains though, the ScriptManager adds the references after the script in the head but I think this is an issue that can't be resolved. I've opted to answer myself but also upvoted crescentfresh.