/// <summary>
        /// Returns a WebResource or ScriptResource URL for script resources that are to be
        /// embedded as script includes.
        /// </summary>
        /// <param name="control">Any control</param>
        /// <param name="type">A type in assembly where resources are located</param>
        /// <param name="resourceName">Name of the resource to load</param>
        /// <param name="renderMode">Determines where in the document the link is rendered</param>
        public void RegisterClientScriptResource(Control control, Type type,
                                                 string resourceName,
                                                 ScriptRenderModes renderMode)
        {
            string resourceUrl = GetClientScriptResourceUrl(control, type, resourceName);

            RegisterClientScriptInclude(control, type, resourceUrl, renderMode);
        }
        /// <summary>
        /// Adds a script to the collection of embedded scripts
        /// </summary>
        /// <param name="scriptUrl"></param>
        /// <param name="renderMode"></param>
        /// <param name="allowMinScript"></param>
        public void AddScript(string scriptUrl, ScriptRenderModes renderMode, bool allowMinScript)
        {
            ScriptItem script = new ScriptItem();

            script.Src            = scriptUrl;
            script.RenderMode     = renderMode;
            script.AllowMinScript = allowMinScript;

            AddScript(script);
        }
        /// <summary>
        /// Renders client script block with the option of rendering the script block in
        /// the Html header
        /// 
        /// For this to work Header must be defined as runat="server"
        /// </summary>
        /// <param name="control">any control that instance typically page</param>
        /// <param name="type">Type that identifies this rendering</param>
        /// <param name="key">unique script block id</param>
        /// <param name="script">The script code to render</param>
        /// <param name="addScriptTags">Ignored for header rendering used for all other insertions</param>
        /// <param name="renderMode">Where the block is rendered</param>
        public void RegisterClientScriptBlock(Control control, Type type, string key, string script, bool addScriptTags, ScriptRenderModes renderMode)
        {
            if (renderMode == ScriptRenderModes.Inherit)
                renderMode = DefaultScriptRenderMode;

            if (control.Page.Header == null ||
                renderMode != ScriptRenderModes.HeaderTop &&
                renderMode != ScriptRenderModes.Header &&
                renderMode != ScriptRenderModes.BottomOfPage)
            {
                RegisterClientScriptBlock(control, type, key, script, addScriptTags);
                return;
            }

            // No dupes - ref script include only once
            const string identifier = "scriptblock_";
            if (HttpContext.Current.Items.Contains(identifier + key))
                return;
            HttpContext.Current.Items.Add(identifier + key, string.Empty);

            StringBuilder sb = new StringBuilder();

            // Embed in header
            sb.AppendLine("\r\n<script type=\"text/javascript\">");
            sb.AppendLine(script);
            sb.AppendLine("</script>");

            int? index = HttpContext.Current.Items[STR_ScriptResourceIndex] as int?;
            if (index == null)
                index = 0;

            if (renderMode == ScriptRenderModes.HeaderTop)
            {
                control.Page.Header.Controls.AddAt(index.Value, new LiteralControl(sb.ToString()));
                index++;
            }
            else if (renderMode == ScriptRenderModes.Header)
                control.Page.Header.Controls.Add(new LiteralControl(sb.ToString()));
            else if (renderMode == ScriptRenderModes.BottomOfPage)
                control.Page.Controls.AddAt(control.Page.Controls.Count - 1, new LiteralControl(sb.ToString()));

            HttpContext.Current.Items[STR_ScriptResourceIndex] = index;
        }
        /// <summary>
        /// Registers a client script reference into the page with the option to specify
        /// the script location in the page
        /// </summary>
        /// <param name="control">Any control instance - typically page</param>
        /// <param name="type">Type that acts as qualifier (uniqueness)</param>
        /// <param name="url">the Url to the script resource</param>
        /// <param name="ScriptRenderModes">Determines where the script is rendered</param>
        public void RegisterClientScriptInclude(Control control, Type type, string url, ScriptRenderModes renderMode)
        {
            if (string.IsNullOrEmpty(url))
                return;

            if (renderMode == ScriptRenderModes.Inherit)
                renderMode = DefaultScriptRenderMode;

            // Extract just the script filename
            string fileId = null;


            // Check resource IDs and try to match to mapped file resources
            // Used to allow scripts not to be loaded more than once whether
            // embedded manually (script tag) or via resources with ClientScriptProxy
            if (url.Contains(".axd?r="))
            {
                string resourceExpr = @"\?r=(*)&";
                Match match = Regex.Match(url, resourceExpr);
                string matchStr = "";
                string res = "";
                if (match.Success)
                {
                    matchStr = match.Groups[1].Value;
                    res = HttpUtility.UrlDecode(matchStr);//StringUtils.ExtractString(url, "?r=", "&", false, true));
                }

                foreach (ScriptResourceAlias item in ScriptResourceAliases)
                {
                    if (item.Resource == res)
                    {
                        fileId = item.Alias + ".js";
                        break;
                    }
                }
                if (fileId == null)
                    fileId = url.ToLower();
            }
            else
                fileId = Path.GetFileName(url).ToLower();

            // Normalize minimized files and plain .js file as the same fileid
            if (fileId.EndsWith("min.js"))
                fileId = fileId.Replace(".min.js", ".js");

            // No dupes - ref script include only once
            if (HttpContext.Current.Items.Contains(STR_SCRIPTITEM_IDENTITIFIER + fileId))
                return;

            HttpContext.Current.Items.Add(STR_SCRIPTITEM_IDENTITIFIER + fileId, string.Empty);

            // just use script manager or ClientScriptManager
            if (control.Page.Header == null || renderMode == ScriptRenderModes.Script || renderMode == ScriptRenderModes.Inline)
            {
                RegisterClientScriptInclude(control, type, url, url);
                return;
            }

            // Retrieve script index in header            
            int? index = HttpContext.Current.Items[STR_ScriptResourceIndex] as int?;
            if (index == null)
                index = 0;

            StringBuilder sb = new StringBuilder(256);

            url = HtmlUtils.ResolveUrl(url);

            // Embed in header
            sb.AppendLine("\r\n<script src=\"" + url + "\" type=\"text/javascript\"></script>");

            if (renderMode == ScriptRenderModes.HeaderTop)
            {
                control.Page.Header.Controls.AddAt(index.Value, new LiteralControl(sb.ToString()));
                index++;
            }
            else if (renderMode == ScriptRenderModes.Header)
                control.Page.Header.Controls.Add(new LiteralControl(sb.ToString()));
            else if (renderMode == ScriptRenderModes.BottomOfPage)
                control.Page.Controls.AddAt(control.Page.Controls.Count - 1, new LiteralControl(sb.ToString()));

            HttpContext.Current.Items[STR_ScriptResourceIndex] = index;
        }
 /// <summary>
 /// Returns a WebResource or ScriptResource URL for script resources that are to be
 /// embedded as script includes.
 /// </summary>
 /// <param name="control">Any control</param>
 /// <param name="type">A type in assembly where resources are located</param>
 /// <param name="resourceName">Name of the resource to load</param>
 /// <param name="renderMode">Determines where in the document the link is rendered</param>
 public void RegisterClientScriptResource(Control control, Type type,
                                          string resourceName,
                                          ScriptRenderModes renderMode)
 {
     string resourceUrl = GetClientScriptResourceUrl(control, type, resourceName);
     RegisterClientScriptInclude(control, type, resourceUrl, renderMode);
 }
        /// <summary>
        /// High level helper function  that is used to load script resources for various AJAX controls
        /// Loads a script resource based on the following scriptLocation values:
        /// 
        /// * WebResource
        ///   Loads the Web Resource specified out of ControlResources. Specify the resource
        ///   that applied in the resourceName parameter
        ///   
        /// * Url/RelativeUrl
        ///   loads the url with ResolveUrl applied
        ///   
        /// * empty string (no value) 
        ///   No action is taken and nothing is embedded into the page. Use this if you manually
        ///   want to load resources
        /// </summary>
        /// <param name="control">The control instance for which the resource is to be loaded</param>
        /// <param name="scriptLocation">WebResource, a virtual path or a full Url. Empty to not embed any script refs (ie. user loads script herself)</param>
        /// <param name="resourceName">The name of the resource when WebResource is used for scriptLocation null otherwise</param>
        /// <param name="topOfHeader">Determines if scripts are loaded into the header whether they load at the top or bottom</param>
        public void LoadControlScript(Control control, string scriptLocation, string resourceName, ScriptRenderModes renderMode)
        {
            // Specified nothing to do
            if (string.IsNullOrEmpty(scriptLocation))
                return;

            if (scriptLocation == "WebResource")
            {
                RegisterClientScriptResource(control, control.GetType(), resourceName, renderMode);
                return;
            }
            RegisterClientScriptInclude(control, control.GetType(),
                                        control.ResolveUrl(scriptLocation),
                                        renderMode);
        }
        /// <summary>
        /// Renders client script block with the option of rendering the script block in
        /// the Html header
        ///
        /// For this to work Header must be defined as runat="server"
        /// </summary>
        /// <param name="control">any control that instance typically page</param>
        /// <param name="type">Type that identifies this rendering</param>
        /// <param name="key">unique script block id</param>
        /// <param name="script">The script code to render</param>
        /// <param name="addScriptTags">Ignored for header rendering used for all other insertions</param>
        /// <param name="renderMode">Where the block is rendered</param>
        public void RegisterClientScriptBlock(Control control, Type type, string key, string script, bool addScriptTags, ScriptRenderModes renderMode)
        {
            if (renderMode == ScriptRenderModes.Inherit)
            {
                renderMode = DefaultScriptRenderMode;
            }

            if (control.Page.Header == null ||
                renderMode != ScriptRenderModes.HeaderTop &&
                renderMode != ScriptRenderModes.Header &&
                renderMode != ScriptRenderModes.BottomOfPage)
            {
                RegisterClientScriptBlock(control, type, key, script, addScriptTags);
                return;
            }

            // No dupes - ref script include only once
            const string identifier = "scriptblock_";

            if (HttpContext.Current.Items.Contains(identifier + key))
            {
                return;
            }
            HttpContext.Current.Items.Add(identifier + key, string.Empty);

            StringBuilder sb = new StringBuilder();

            // Embed in header
            sb.AppendLine("\r\n<script type=\"text/javascript\">");
            sb.AppendLine(script);
            sb.AppendLine("</script>");

            int?index = HttpContext.Current.Items[STR_ScriptResourceIndex] as int?;

            if (index == null)
            {
                index = 0;
            }

            if (renderMode == ScriptRenderModes.HeaderTop)
            {
                control.Page.Header.Controls.AddAt(index.Value, new LiteralControl(sb.ToString()));
                index++;
            }
            else if (renderMode == ScriptRenderModes.Header)
            {
                control.Page.Header.Controls.Add(new LiteralControl(sb.ToString()));
            }
            else if (renderMode == ScriptRenderModes.BottomOfPage)
            {
                control.Page.Controls.AddAt(control.Page.Controls.Count - 1, new LiteralControl(sb.ToString()));
            }

            HttpContext.Current.Items[STR_ScriptResourceIndex] = index;
        }
        /// <summary>
        /// Registers a client script reference into the page with the option to specify
        /// the script location in the page
        /// </summary>
        /// <param name="control">Any control instance - typically page</param>
        /// <param name="type">Type that acts as qualifier (uniqueness)</param>
        /// <param name="url">the Url to the script resource</param>
        /// <param name="ScriptRenderModes">Determines where the script is rendered</param>
        public void RegisterClientScriptInclude(Control control, Type type, string url, ScriptRenderModes renderMode)
        {
            if (string.IsNullOrEmpty(url))
            {
                return;
            }

            if (renderMode == ScriptRenderModes.Inherit)
            {
                renderMode = DefaultScriptRenderMode;
            }

            // Extract just the script filename
            string fileId = null;


            // Check resource IDs and try to match to mapped file resources
            // Used to allow scripts not to be loaded more than once whether
            // embedded manually (script tag) or via resources with ClientScriptProxy
            if (url.Contains(".axd?r="))
            {
                string res = HttpUtility.UrlDecode(StringUtils.ExtractString(url, "?r=", "&", false, true));
                foreach (ScriptResourceAlias item in ScriptResourceAliases)
                {
                    if (item.Resource == res)
                    {
                        fileId = item.Alias + ".js";
                        break;
                    }
                }
                if (fileId == null)
                {
                    fileId = url.ToLower();
                }
            }
            else
            {
                fileId = Path.GetFileName(url).ToLower();
            }

            // Normalize minimized files and plain .js file as the same fileid
            if (fileId.EndsWith("min.js"))
            {
                fileId = fileId.Replace(".min.js", ".js");
            }

            // No dupes - ref script include only once
            if (HttpContext.Current.Items.Contains(STR_SCRIPTITEM_IDENTITIFIER + fileId))
            {
                return;
            }

            HttpContext.Current.Items.Add(STR_SCRIPTITEM_IDENTITIFIER + fileId, string.Empty);

            // just use script manager or ClientScriptManager
            if (control.Page.Header == null || renderMode == ScriptRenderModes.Script || renderMode == ScriptRenderModes.Inline)
            {
                RegisterClientScriptInclude(control, type, url, url);
                return;
            }

            // Retrieve script index in header
            int?index = HttpContext.Current.Items[STR_ScriptResourceIndex] as int?;

            if (index == null)
            {
                index = 0;
            }

            StringBuilder sb = new StringBuilder(256);

            url = WebUtils.ResolveUrl(url);

            // Embed in header
            sb.AppendLine("\r\n<script src=\"" + url + "\" type=\"text/javascript\"></script>");

            if (renderMode == ScriptRenderModes.HeaderTop)
            {
                control.Page.Header.Controls.AddAt(index.Value, new LiteralControl(sb.ToString()));
                index++;
            }
            else if (renderMode == ScriptRenderModes.Header)
            {
                control.Page.Header.Controls.Add(new LiteralControl(sb.ToString()));
            }
            else if (renderMode == ScriptRenderModes.BottomOfPage)
            {
                control.Page.Controls.AddAt(control.Page.Controls.Count - 1, new LiteralControl(sb.ToString()));
            }

            HttpContext.Current.Items[STR_ScriptResourceIndex] = index;
        }
        /// <summary>
        /// High level helper function  that is used to load script resources for various AJAX controls
        /// Loads a script resource based on the following scriptLocation values:
        ///
        /// * WebResource
        ///   Loads the Web Resource specified out of ControlResources. Specify the resource
        ///   that applied in the resourceName parameter
        ///
        /// * Url/RelativeUrl
        ///   loads the url with ResolveUrl applied
        ///
        /// * empty string (no value)
        ///   No action is taken and nothing is embedded into the page. Use this if you manually
        ///   want to load resources
        /// </summary>
        /// <param name="control">The control instance for which the resource is to be loaded</param>
        /// <param name="scriptLocation">WebResource, a virtual path or a full Url. Empty to not embed any script refs (ie. user loads script herself)</param>
        /// <param name="resourceName">The name of the resource when WebResource is used for scriptLocation null otherwise</param>
        /// <param name="topOfHeader">Determines if scripts are loaded into the header whether they load at the top or bottom</param>
        public void LoadControlScript(Control control, string scriptLocation, string resourceName, ScriptRenderModes renderMode)
        {
            // Specified nothing to do
            if (string.IsNullOrEmpty(scriptLocation))
            {
                return;
            }

            if (scriptLocation == "WebResource")
            {
                RegisterClientScriptResource(control, control.GetType(), resourceName, renderMode);
                return;
            }
            RegisterClientScriptInclude(control, control.GetType(),
                                        control.ResolveUrl(scriptLocation),
                                        renderMode);
        }
        /// <summary>
        /// Helper function that is used to load script resources for various AJAX controls
        /// Loads a script resource based on the following scriptLocation values:
        /// 
        /// * WebResource
        ///   Loads the Web Resource specified out of ControlResources. Specify the resource
        ///   that applied in the resourceName parameter
        ///   
        /// * Url/RelativeUrl
        ///   loads the url with ResolveUrl applied
        ///   
        /// * empty (no value) 
        ///   No action is taken
        /// </summary>
        /// <param name="control">The control instance for which the resource is to be loaded</param>
        /// <param name="scriptLocation">WebResource, a Url or empty (no value)</param>
        /// <param name="resourceName">The name of the resource when WebResource is used for scriptLocation</param>
        /// <param name="topOfHeader">Determines if scripts are loaded into the header whether they load at the top or bottom</param>
        public void LoadControlScript(Control control, string scriptLocation, string resourceName, ScriptRenderModes renderMode)
        {
            ClientScriptProxy proxy = ClientScriptProxy.Current;

            // Specified nothing to do
            if (string.IsNullOrEmpty(scriptLocation))
                return;

            ScriptItem scriptItem = new ScriptItem();
            scriptItem.Src = scriptLocation;
            scriptItem.RenderMode = renderMode;

            if (scriptLocation == "WebResource")
            {
                scriptItem.Resource = resourceName;
                scriptItem.ResourceAssembly = null;
                scriptItem.Src = resourceName;
            }

            //// It's a relative url
            //if (ClientScriptProxy.LoadScriptsInHeader)
            //    proxy.RegisterClientScriptIncludeInHeader(control, control.GetType(),
            //                                            control.ResolveUrl(scriptLocation), topOfHeader);
            //else
            //    proxy.RegisterClientScriptInclude(control, control.GetType(),
            //                            Path.GetFileName(scriptLocation), control.ResolveUrl(scriptLocation));

            AddScript(scriptItem);
        }
        /// <summary>
        /// Adds a script to the collection of embedded scripts
        /// </summary>
        /// <param name="scriptUrl"></param>
        /// <param name="renderMode"></param>
        /// <param name="allowMinScript"></param>
        public void AddScript(string scriptUrl, ScriptRenderModes renderMode, bool allowMinScript)
        {
            ScriptItem script = new ScriptItem();
            script.Src = scriptUrl;
            script.RenderMode = renderMode;
            script.AllowMinScript = allowMinScript;

            AddScript(script);
        }
        /// <summary>
        /// Helper function that is used to load script resources for various AJAX controls
        /// Loads a script resource based on the following scriptLocation values:
        ///
        /// * WebResource
        ///   Loads the Web Resource specified out of ControlResources. Specify the resource
        ///   that applied in the resourceName parameter
        ///
        /// * Url/RelativeUrl
        ///   loads the url with ResolveUrl applied
        ///
        /// * empty (no value)
        ///   No action is taken
        /// </summary>
        /// <param name="control">The control instance for which the resource is to be loaded</param>
        /// <param name="scriptLocation">WebResource, a Url or empty (no value)</param>
        /// <param name="resourceName">The name of the resource when WebResource is used for scriptLocation</param>
        /// <param name="topOfHeader">Determines if scripts are loaded into the header whether they load at the top or bottom</param>
        public void LoadControlScript(Control control, string scriptLocation, string resourceName, ScriptRenderModes renderMode)
        {
            ClientScriptProxy proxy = ClientScriptProxy.Current;

            // Specified nothing to do
            if (string.IsNullOrEmpty(scriptLocation))
            {
                return;
            }

            ScriptItem scriptItem = new ScriptItem();

            scriptItem.Src        = scriptLocation;
            scriptItem.RenderMode = renderMode;

            if (scriptLocation == "WebResource")
            {
                scriptItem.Resource         = resourceName;
                scriptItem.ResourceAssembly = null;
                scriptItem.Src = resourceName;
            }

            //// It's a relative url
            //if (ClientScriptProxy.LoadScriptsInHeader)
            //    proxy.RegisterClientScriptIncludeInHeader(control, control.GetType(),
            //                                            control.ResolveUrl(scriptLocation), topOfHeader);
            //else
            //    proxy.RegisterClientScriptInclude(control, control.GetType(),
            //                            Path.GetFileName(scriptLocation), control.ResolveUrl(scriptLocation));

            AddScript(scriptItem);
        }