惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

I
Intezer
V
Vulnerabilities – Threatpost
Google Online Security Blog
Google Online Security Blog
T
The Exploit Database - CXSecurity.com
C
CXSECURITY Database RSS Feed - CXSecurity.com
AWS News Blog
AWS News Blog
G
GRAHAM CLULEY
P
Privacy & Cybersecurity Law Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
Cybersecurity and Infrastructure Security Agency CISA
N
News | PayPal Newsroom
T
Tenable Blog
Spread Privacy
Spread Privacy
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
S
Secure Thoughts
P
Privacy International News Feed
IT之家
IT之家
Project Zero
Project Zero
T
The Blog of Author Tim Ferriss
Engineering at Meta
Engineering at Meta
大猫的无限游戏
大猫的无限游戏
博客园_首页
GbyAI
GbyAI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
量子位
雷峰网
雷峰网
Apple Machine Learning Research
Apple Machine Learning Research
Hacker News: Ask HN
Hacker News: Ask HN
Google DeepMind News
Google DeepMind News
MongoDB | Blog
MongoDB | Blog
N
Netflix TechBlog - Medium
Martin Fowler
Martin Fowler
NISL@THU
NISL@THU
I
InfoQ
D
DataBreaches.Net
有赞技术团队
有赞技术团队
K
Kaspersky official blog
Security Latest
Security Latest
The Register - Security
The Register - Security
Hugging Face - Blog
Hugging Face - Blog
S
Security @ Cisco Blogs
P
Proofpoint News Feed
M
MIT News - Artificial intelligence
H
Hackread – Cybersecurity News, Data Breaches, AI and More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
AI
AI
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Proofpoint News Feed
Security Archives - TechRepublic
Security Archives - TechRepublic
N
News and Events Feed by Topic

博客园 - shuang

heart or house? Dos for -- by 随风 - shuang C--Pointer Raid -----asp web 报表 - shuang ----[创业指南]给海归技术创业兄弟的九个忠告 --设计模式--Hibernate about avast job desc 把INT转换成2进制等 private/实现有多个相同方法的接口 使用接口改变已经装箱的值类型的字段 struct也有方法成员 virtual 集成资源文件 const -readonly- static readonly csm2 ClientScriptManager html______1
脚本---用函数模拟类
shuang · 2007-12-18 · via 博客园 - shuang

让我们先实现组件化的AutoFlex脚本:

function AutoFlex(id,maxHeight)
{    
    
this._id = id;
    
this.maxHeight = maxHeight;

}


AutoFlex.prototype._onPropertyChange 
= function()
{
    
if(this.maxHeight)
     
{
        
this._element.style.height =
         ( 
this._element.scrollHeight > this.maxHeight ) ? this.maxHeight : this._element.scrollHeight + this._element.offsetHeight - this._element.clientHeight;          

    }

    
else
     
{
        
this._element.style.height = this._element.scrollHeight 
            
+ ( this._element.offsetHeight - this._element.clientHeight );

    }
  

}


AutoFlex.prototype._getPropertyChangeHandler 
= function(){

    
var obj = this;

    
return function (){

        obj._onPropertyChange.call(obj);

    }


}


AutoFlex.prototype.initiate 
= function(){

    
this._element = document.getElementById(this._id);

    
if(this._element)
    
{
        
this._element.onpropertychange = this._getPropertyChangeHandler();
    }


}



上面这段代码我们遵循这样的代码规范:
(1)类名使用Pascal命名法,函数使用骆驼法,这一点很重要,因为JavaScript本没有类这个概念,我们使用Function模拟类,为了区别function定义的是类的概念还是函数的概念,我们使用不同的命名法。
(2)类的属性在构造函数中定义和初始化,类的函数中通过prototype添加。
(3)非对外的成员名使用_开头。
*************************************************
这段代码需要注意以下几点:
(1)在JavaScript中,0相当于false,null也相当于false,所以我们只需判断if(this.maxHeight)就能覆盖没有传maxHeight参数和maxHeight参数为0的两种情况。
(2)在附加事件响应程序时,我们不是直接写this._element.onpropertychange = this._onPropertyChange而是this._element.onpropertychange = this._getPropertyChangeHandler()。这是为什么呢?原来如果我们使用前一种写法,当_onPropertyChange方法被事件触发时,它的执行上下文,也就是this指针是指向触发事件的对象或window对象,这是JavaScript中事件的一个特别需要重视的特点,如果是这样的话,_onPropertyChange()方法中的代码将不能正确执行。在后一种写法中,我们通过JavaScript的闭包特性和Function.call()方法使得_onPropertyChange()方法在执行时能得到期待的this指针。
***************************************************

注:闭包——函数始终可以使用定义它时在它外围的(即它可访问到的)变量,而无论它在何时执行。如上例的_getPropertyChangeHandler()方法中的代码,我们用obj变量保存this的指针,那么接下来定义的函数始终可以访问到obj变量,即使是在被事件触发时也是如此。call——Javascript中的Function原型上有两个功能类似的方法——call和apply,它们都用来执行当前函数,但被执行函数中的this指针指向call或apply方法的第一个参数,如上例中的obj._onPropertyChange.call(obj),这个语句被事件触发时指针this本来是指向window对象的,然而我们使用call方法使得_onPropertyChange方法内部的语句访问的this指针指向obj对象

call方法和apply方法的区别在于传递参数的方式不同,call方法把第一个参数作为被调用方法的this指针,其余参数作为被调用方法的参数,apply也把第一个参数作为被调用方法的this指针,然后用一个数组把参数打包传给被调函数。如,myFunction.call(context,arg0,arg1,arg2)和myFunction.apply(context,[arg0,arg1,arg2]);

准备好了组件化的脚本后,控件的实现变得非常简单:
<%@ Register TagPrefix="cc1" Namespace="ClassLibrary1" Assembly="ClassLibrary1" %> 该指令注册自定义控件

public class AutoFlexTextArea:TextBox

    
{

        
bool _supportJS;

        
const string AUTOFLEXJS = @"

    function AutoFlex(id,maxHeight){

        this._id = id;

        this.maxHeight = maxHeight;

    }

    AutoFlex.prototype._onPropertyChange = function(){

        if(this.maxHeight){

            this._element.style.height =

             ( this._element.scrollHeight > this.maxHeight ) ? this.maxHeight : 

                this._element.scrollHeight 

+ ( this._element.offsetHeight - this._element.clientHeight);          

        }

        else{

            this._element.style.height = this._element.scrollHeight 

                + ( this._element.offsetHeight - this._element.clientHeight );

        }  

    }

    AutoFlex.prototype._getPropertyChangeHandler = function(){

        var obj = this;

        return function (){

            obj._onPropertyChange.call(obj);

        }

    }

    AutoFlex.prototype.initiate = function(){

        this._element = document.getElementById(this._id);

        if(this._element){

            this._element.onpropertychange = this._getPropertyChangeHandler();

        }

    }
";

        [DefaultValue(
0)]

        [Category(
"Behavior")]

        [Description(
"最大伸展高度")]

        
public int MaxHeight
       
{    
            get{
                
if (ViewState["MaxHeight"== null)
                {    return 0;    }

                
return (int)ViewState["MaxHeight"];

            }

           
set{
                   ViewState["MaxHeight"= value;

            }


        }


        [DesignerSerializationVisibility

                    (DesignerSerializationVisibility.Hidden)]

        [Browsable(
false)]

        [EditorBrowsable(EditorBrowsableState.Advanced)]

        
public override TextBoxMode TextMode

        
{

            
get

            
{

                
return TextBoxMode.MultiLine;

            }


            
set

            
{

                
throw new NotSupportedException(

"Can not change the TextMode property");

            }


        }


        
void DetermineJS()

        
{

            
if (!DesignMode)

            
{

                
if (Page.Request.Browser.EcmaScriptVersion.Major > 0 

&& Page. Request.Browser.W3CDomVersion.Major > 0)

                
{

                    
this._supportJS = true;

                }


            }


        }


        

        
protected override void OnPreRender(EventArgs e)

        
{

            
base.OnPreRender(e);

            DetermineJS();

            
if (_supportJS)

            
{

                
if (!Page.ClientScript.IsClientScriptBlockRegistered(

this. GetType(),"AUTOFLEXJS"))

                
{

                    Page.ClientScript.RegisterClientScriptBlock(

this.GetType(), "AUTOFLEXJS", AUTOFLEXJS, true);

                }


            }


        }


        
protected override void Render(HtmlTextWriter writer)

        
{

            
base.Render(writer);

            
if (_supportJS)

            
{

                Page.ClientScript.RegisterStartupScript(

this.GetType(), this.UniqueID,

                    
string.Format("    var {0}_AutoFlex = 

new AutoFlex('{0}',{1});\r\n    {0}_AutoFlex.initiate();\r\n",

                    
this.UniqueID,this.MaxHeight.ToString()), true);

            }


        }


这段代码非常简单,AutoFlexTextArea类从TextBox类继承。为了隐藏TextBox的TextMode属性,重写了这个属性,并且不允许用户设置TextMode属性
此外新增了MaxHeight属性,用来指定最大扩展高度
然后重写OnPreRender()方法,检测访问浏览器对脚本的支持能力,并输出AutoFlex组件脚本,通过IsClientScriptBlockRegistered()方法保证在同样的页面中,这段脚本只会输出一次
最后重写Render()方法,在页面表单的最后注册初始化客户端组件所需的脚本.
******************************************************

生成控件,放入页面中进行测试:

<cc1:autoflextextarea id="AutoFlexTextArea1" runat="server"></cc1:autoflextextarea>

<cc1:autoflextextarea id="AutoFlexTextArea2"

runat="server" MaxHeight="200"></cc1:autoflextextarea>

最终呈现的页面内容如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head><title>

                    无标题页

</title></head>

<body>

    <form name="form1" method="post" action="TestAutoFlexTextArea.aspx" id="form1">

<div>

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTEyMj U4MzUwMGRkE8+2KGaUuMKOsu+evZ76vSgAYMU=" />

</div>

<script type="text/javascript">

<!--

    function AutoFlex(id,maxHeight){

        //省略AutoFlex组件代码;

    }

// -->

</script>

        <div>

            <textarea name="AutoFlexTextArea1" rows="2" cols="20" id="AutoFlexTextArea1"></textarea>

            <textarea name="AutoFlexTextArea2" rows="2" cols="20" id="AutoFlexTextArea2"></textarea>

        </div>

<div>

            <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAwL/88OJCQKmoPGEDAKloPGEDNkP9kNJ1Pg3kQ7qvP+7/kqXZYV0" />

</div>

<script type="text/javascript">

<!--

    var AutoFlexTextArea1_AutoFlex = new AutoFlex('AutoFlexTextArea1',0);

    AutoFlexTextArea1_AutoFlex.initiate();

    var AutoFlexTextArea2_AutoFlex = new AutoFlex('AutoFlexTextArea2',200);

    AutoFlexTextArea2_AutoFlex.initiate();

// -->

</script>

</form>

</body>

</html>