随笔-71  评论-634  文章-4  trackbacks-33

如何在服务端(Page.Write)调用自定义的JS方法

-Written by 浪子@cnblogs.com  (06-08-28)


自从[JavaScript]自定义MessageBox一文发布以后,很多网友都来信询问,如何在服务端调用ShowInfo方法,周末休息想了个折中的办法来实现。

首先,我们应该可以先明确,为什么我们用Page.Write把自定义的JS方法输出到页面上为什么IE不能识别,会出现“XXX未定义”的错误。原因很简单,因为我们用Page.Write输出的脚本是出现在页面的最顶端。IE读到是javascript函数的时候,就开始执行,但是此时我们link的js文件并未被IE读入,所以IE无法识别我们定义在js文件里面的方法。那write alert为什么可以呢?因为alert是IE内嵌的脚本功能函数,不管有没有页面,IE都认得它。

 

找到问题所在,自然就好解决了:

1、把我们自定义的方法内嵌到IE里面。 ---> 看起来有点异想天开,呵呵

2、等页面载入完成后再触发事件。 --->触发事件,没错。

 

如何知道页面是否载入完成呢?

1、通过document的状态

2、通过事件触发(windows.onload)

 

第一种好像比较不保险,有时候明明已经全部载完了,它还是一直显示在传送数据(FF此情况最明显),所以还是用事件比较保险一点。

 

定义一个简单方法,挂载到windows.onload里面,执行的时候做一个标识

 

var loadComplete = false;
function LoadCompleted()
{
loadComplete= true;
}
window.attachEvent("onload",LoadCompleted);

呵呵,这样我们只要通过判断loadComplete来取得页面是否载入完毕了。

 

var mImgdir = "";
var mCaption = "caption";
var mMsg = "Message";
var mOkClick= null;
function ShowMessage(imgdir,caption,msg,OkClick)
{
if(loadComplete)
{
KMessageBox.ShowInfo(mImgdir,mCaption,mMsg,mOkClick);
}
}

这样子在loadComplete未false的情况下,我们就不会去执行KMessageBox.ShowInfo()方法,只然就不会出现JS错误提示了。

 

单单这样子,还不行,因为输出的这样的脚本,IE只在输出页面的时候执行了一次,但是此时loadComplete=false,所以,我们需要定时检测页面是否载入完毕。说到定时,只然是祭出setTimeout & setInterval. 我们这里需要不停的检测,故使用setInterval方法。最终代码如下:

 

var loadComplete = false;
var mImgdir = "";
var mCaption = "caption";
var mMsg = "Message";
var mOkClick= null;
var timerID;
function ShowMessage(imgdir,caption,msg,OkClick)
{
if(loadComplete)
{
KMessageBox.ShowInfo(mImgdir,mCaption,mMsg,mOkClick);
     //卸载此事件
window.detachEvent("onload",function(){LoadCompleted;});
//停止定时触发 window.clearInterval(timerID);

    }

}

function LoadCompleted() { loadComplete=true; }

window.attachEvent("onload",LoadCompleted);

//设置定时检测机制
timerID = window.setInterval(ShowMessage,1);

 

当然以上代码只兼容IE,因为使用attachEvent 和 detachEvent,至于让他兼容其他浏览器可以参看[JavaScript]自定义Title的显示方式一文中的处理方式:

 

if(!document.attachEvent)//Not IE
{
document.attachEvent = function(){document.addEventListener(arguments[0].substr(2),arguments[1],arguments[2])}
}
if(!window.attachEvent)//Not IE
{
window.attachEvent = function(){window.addEventListener(arguments[0].substr(2),arguments[1],arguments[2])}
}

 

在服务端,只要StringBuilder出以上的脚本,然后Write出来就可以了。上面也只是提供了一种思路,当然还会有其他的办法,比如我不适用定时检测,我直接挂载到windows.onload里面,让页面自动监听,自动执行,也未尝不可:),正所谓条条大路通罗马嘛~~~~~

 

以上思路来自yui,并且yui实现了一个更漂亮的自定义MessageBox,有兴趣的朋友可以共同研究下。

posted on 2006-08-28 10:32 浪子 阅读(5836) 评论(19)  编辑 收藏 所属分类: JavaScript/CSS

评论:
#1楼 2006-08-28 13:14 | Harrison      
为什么不用:

public virtual void RegisterStartupScript(
string key,
string script
);


允许 ASP.NET 服务器控件在 Page 中发出客户端脚本块。
[C#]
public virtual void RegisterStartupScript(
string key,
string script
);


参数
key
标识脚本块的唯一键。
script
要发送到客户端的脚本的内容。
备注
与 RegisterClientScriptBlock 方法类似,该方法在 Page 对象的 <form runat= server> 元素的结束标记之前发出该脚本。发出脚本块时已定义了呈现该页的对象时,因此必须同时包括 <script> 元素的两个标记。

通过使用 key 标识脚本,多个服务器控件实例可以请求该脚本块,而不用将其发送到输出流两次。

具有相同 key 参数值的任何脚本块均被视为重复的。

  回复  引用  查看    
#2楼[楼主] 2006-08-28 14:06 | 浪子      
@Harrison
这个只是注册脚本程序块,但是不会执行。

  回复  引用  查看    
#3楼 2006-08-28 18:39 | Harrison      
@浪子
RegisterStartupScript应该是跟在前台</form>前面直接写Script块一样的,如果里面你写的是一个函数当然不会执行,但如果是JS的语句是会执行的

  回复  引用  查看    
#4楼[楼主] 2006-08-28 19:08 | 浪子      
@Harrison
你试一下先,自定义函数和默认函数。

我这里是跑不起来。

这个运行正常
Page.ClientScript.RegisterStartupScript(this.GetType(), "test", "<script type=\"text/javascript\">alert('ok');</script>");

这个不反应,但是不会出错,因为没有被执行
Page.ClientScript.RegisterStartupScript(this.GetType(), "test", "<script type=\"text/javascript\">KMessageBox.ShowInfo('','test','test',null);</script>");

  回复  引用  查看    
#5楼 |

  
#6楼 2006-08-29 09:20 | adonio      
没有这么麻烦吧,,要保证JS被加载完了再执行就是两个方法。
一是在JS声明在使用defer 如 <script type="text/javascript" defer="defer"></script>,这样可以保证JS完了再执行
再就是有用 <asp:Literal >控件,把他放在页面最后面。。对他赋值就行了,值就是要执行的脚本,如
<script type=\"text/javascript\">alert('ok');</script>"

  回复  引用  查看    
#7楼[楼主] 2006-08-29 10:02 | 浪子      
@adonio

按你的方法,同样是内嵌的函数(alert)可以,自定义的不行。

//不行
Page.Response.Write("<script type=\"text/javascript\" defer=\"defer\">KMessageBox.ShowInfo('','test','test',null);</script>");
//不行
Page.ClientScript.RegisterStartupScript(this.GetType(), "test", "<script type=\"text/javascript\" defer=\"defer\">KMessageBox.ShowInfo('','test','test',null);</script>");
//不行
this.Literal1.Text = "<script type=\"text/javascript\">KMessageBox.ShowInfo('','test','test',null);</script>";
//可行
this.Literal1.Text = "<script type=\"text/javascript\">alert('ok');</script>";

  回复  引用  查看    
#8楼 2006-08-29 12:29 | Harrison      
没试过vs2005,但是在vs2003里面调用页面的函数是没有问题的
  回复  引用  查看    
#9楼[楼主] 2006-08-29 14:11 | 浪子      
@Harrison
vs只是工具,不会对asp.net运行时产生影响。

调用页面的函数?不大明白你的页面的函数是什么概念。

如果你是直接写在</form>之前的js函数,我想应该是可以认得的。因为你已经直接输出到它的前面了,然后调用它。就像我文中的ShowMessage方法时一样的。

p.s. 我调用的是外部link进来的js的方法。

  回复  引用  查看    
#10楼 2006-08-29 17:32 | adonio      
郁闷啊,刚刚遭遇到楼主说的问题且更复杂,现在还没有搞定。。atlas下的脚本掉用WEB 服务,用按钮点没事。如果放在onload中自动运行就有问题了,楼主的方法在这里也行不通

  回复  引用  查看    
#11楼[楼主] 2006-08-30 09:00 | 浪子      
@adonio
需要先找到为什么不行。你所谓的用按钮点是? 客户端的onclick嘛?
atlas还没有研究,可以问下Dflying,他是atlas专家的说

  回复  引用  查看    
#12楼 |

  
#13楼[楼主] 2007-04-11 17:39 | 浪子      
@lethe
请参照我回复@adonio 的内容,关键是外部引入js,而不是硬编码在页面上面的代码

  回复  引用  查看    
#14楼 2007-05-06 14:44 | 代码乱了      
Page.Write的方式很不好
明明有RegisterStartupScript却不用

  回复  引用  查看    
#15楼[楼主] 2007-05-06 16:55 | 浪子      
@代码乱了
请注意前提条件。

外部引入的js的里面的函数。

  回复  引用  查看    
#16楼 2007-07-22 17:57 | doasp      
楼主说得没错 我也遇到过这个问题 外部引入的JS文件 是得另辟奇径才能解决在服务端调用的问题 类似的提示窗口还有很多 比如jQuery的插件thickbox,基于prototype的jqModal、modalbox,submodal等等 各有千秋
  回复  引用  查看    
#17楼 |

  
#18楼[楼主] 2007-08-07 12:14 | 浪子      
@Motion
最近的系统,也使用了RegisterStartupScript,似乎没出现问题,之前的不知道为什么测试一直通不过:-),太久了也记不得了,不过当时真的测试没有通过,不知道是不是自己测试搞错了^_^

  回复  引用  查看    



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 488090


相关文章:

相关链接: