当前位置: 代码迷 >> Web前端 >> prototype里Form.Element.focus(element) 方法是否实现异常
  详细解决方案

prototype里Form.Element.focus(element) 方法是否实现异常

热度:575   发布时间:2012-11-23 00:03:43.0
prototype里Form.Element.focus(element) 方法是否实现错误?
今天上午没事做,在公司拿着买到的 <<prototype与script.aculo.us终极揭秘>>一书看,无意中发现了一个比较有趣的问题,不知道是不是 prototype.js自己的bug,拿上来让各位鉴定一下。
   参照prototype.js的官方的api文档,Form.Element.focus(element) -> HTMLElement,他的意思应该是调用这个focus()方法之后返回的是应该是一个被prototye扩张的 HTMLElement,然后可以拿着返回的对象可以继续进行链式调用。可事实上并非如此。我自己测试了一把。下面的代码给的不全。要测试的话需要自己补全。

 <script type="text/javascript">
        	function test_focus()
	{
	    $("clickme").observe("click",function(){
		alert(Object.isString(Form.Element.focus('username')))
		Form.Element.focus('username').disable().setValue("hahahaha");
	      });	
	}
        	document.observe("dom:loaded",test_focus)
  </script>
  <body>
    <form id="login">
    	username : <input type="text" id="username" value="hehehehe"><br>
	password : <input type="text" id="password"><br>
	<input type="button" value="click me" id="clickme"><br>
    </form>
   </body>


上面的代码运行到alert()部分的时候,会提示true,也就是说他返回的是一个String,然后会报出一个Form.Element.focus("username").disable is not a function的错误。

查看prototype.js的源代码,我们看到这个方法的定义,他其实就是直接返回了传进去的element,根本就没做扩展,所以所谓的链式编程到这里就不能继续下去了。
  Form.Element = {
      focus: function(element) {
      $(element).focus();
      return element;
   },

  select: function(element) {
    $(element).select();
    return element;
  }
 };


我直接把它hack掉之后上面的代码就可以正常运行了
  Form.Element = {
      focus: function(element) {
      $(element).focus();
      return $(element);
   },

  select: function(element) {
    $(element).select();
    return $(element);
  }
 };


我不知道这是不是prototype.js的bug,我这样的修改也只能说能测试通过我写的demo,所以拿出来供大家谈论一下。

1 楼 xuyao 2008-12-09  
会不会你看的prototype版本和API不对
2 楼 zy8643954 2008-12-09  
xuyao 写道
会不会你看的prototype版本和API不对

我一开始也是这么认为,后来在官方网站下了最新的1.6.0.3都是一样的。
3 楼 long_biti 2008-12-14  

$('username').focus().disable();
prototype1.5开始更建议直接使用上述形式来调用。
而focus方法的问题应该是因为在从老的版本过度过来的时候没有改完善吧。参考disable方法,在方法开始的地方直接使用:
element = $(element);

像lz写的:
$(element).focus();  
    return $(element); 
在prototype好像是不建议多次对一个element使用$(),可能存在一些无谓的性能损耗。
4 楼 vipmail 2008-12-30  
element = $(element);  支持
5 楼 hanjs 2009-01-02  
不知道lz看的是哪个版本的?

好像不是你这样用的吧

setValue: function(element, value) {
    element = $(element);
    var method = element.tagName.toLowerCase();
    Form.Element.Serializers[method](element, value);
    return element;
  },



<script src="prototype-1.6.0.3.js" type="text/javascript"> </script>

<script type="text/javascript">   
        function test_focus()   
{   
    $("clickme").observe("click",function(){   
    //alert(Object.isString(Form.Element.focus('username')))   
    Form.Element.disable('username');
    Form.Element.setValue('username',"hahahaha");   
      });      
}  
        document.observe("dom:loaded",test_focus)   
 </script>   
 <body>   
   <form id="login">   
    username : <input type="text" id="username" value="hehehehe"><br>   
password : <input type="text" id="password"><br>   
<input type="button" value="click me" id="clickme"><br>   
   </form>   
  </body> 
6 楼 zy8643954 2009-01-02  
ls的好像没有完全理解我说的意思啊。
7 楼 downpour 2009-01-02  
prototype并没有告诉你Form.Element.focus(element)返回的对象是被prototype加强过的,只是你个人的猜测而已。

事实上,类似像focus这样的函数,只是为了做焦点定位,继续使用其返回值的场景很少。所以返回值也不应该变成一个加强过的对象。

不要动不动就说是框架的bug,我认为还是先动动脑筋别人为什么要这样实现为好。
8 楼 zy8643954 2009-01-02  
downpour 写道
prototype并没有告诉你Form.Element.focus(element)返回的对象是被prototype加强过的,只是你个人的猜测而已

事实上,类似像focus这样的函数,只是为了做焦点定位,继续使用其返回值的场景很少。所以返回值也不应该变成一个加强过的对象。

不要动不动就说是框架的bug,我认为还是先动动脑筋别人为什么要这样实现为好。


我参考的是prototype-160-api.pdf官方文档,文档里写的是focus(element) -> HTMLElement。我没有说是它的错误。但是文档和实现确实不一致。

focus(element) -> HTMLElement
Gives keyboard focus to an element.
Form.Element.focus('searchbox')
// Almost equivalent, but does NOT return the form element
// (uses the native focus() method):
$('searchbox').focus()
9 楼 downpour 2009-01-03  
zy8643954 写道
downpour 写道
prototype并没有告诉你Form.Element.focus(element)返回的对象是被prototype加强过的,只是你个人的猜测而已

事实上,类似像focus这样的函数,只是为了做焦点定位,继续使用其返回值的场景很少。所以返回值也不应该变成一个加强过的对象。

不要动不动就说是框架的bug,我认为还是先动动脑筋别人为什么要这样实现为好。


我参考的是prototype-160-api.pdf官方文档,文档里写的是focus(element) -> HTMLElement。我没有说是它的错误。但是文档和实现确实不一致。

focus(element) -> HTMLElement
Gives keyboard focus to an element.
Form.Element.focus('searchbox')
// Almost equivalent, but does NOT return the form element
// (uses the native focus() method):
$('searchbox').focus()


focus(element) -> HTMLElement就代表返回的对象就必须要被prototype加强嘛?这纯粹是你的理解。

我们来看看另外一个Element的方法,prototype的文档是怎么说的:

引用


down(element[, cssRule][, index = 0]) -> HTMLElement | undefined


The Element.down method is part of Prototype’s ultimate DOM traversal toolkit (check out Element.up, Element.next and Element.previous for some more Prototypish niceness). It allows precise index-based and/or CSS rule-based selection of any of the element’s descendants.

As it totally ignores text nodes (it only returns elements), you don’t have to worry about whitespace nodes.

And as an added bonus, all elements returned are already extended allowing chaining



如果返回的HTMLElement支持chaining,并被prototype加强,在文档中自会详细说明。

对于focus这种方法,文档中本身就没有提到支持chaining。从这个方法的语义本身来说,也不需要支持chaining,因为在调用focus这个函数之后,几乎没有场景需要让其进行后续操作。
10 楼 hanjs 2009-01-03  
zy8643954 写道
ls的好像没有完全理解我说的意思啊。


我看了一下,确实是和文档说的有出入。LS的也看看文档吧,首先要明确到底什么是HTMLElement
11 楼 downpour 2009-01-04  
hanjs 写道
zy8643954 写道
ls的好像没有完全理解我说的意思啊。


我看了一下,确实是和文档说的有出入。LS的也看看文档吧,首先要明确到底什么是HTMLElement


我都把文档的说明打上红色标记了,为啥不稍微看一下呢?

什么是HTMLElement?看看《JavaScript权威指南》:

引用
Availability

DOM Level 1 HTML

Inherits from/Overrides

Node->Element->HTMLElement


哪里说了HTMLElement就一定要被prototype加强过?


12 楼 zy8643954 2009-01-04  
downpour  说的是正确的,谢谢你让我明白了这个。
13 楼 waitingmyself 2009-01-05  
API:The activate method is a nifty way to both focus a form field and select its current text, all in one portable JavaScript call.

源码:1.6.0.2
activate: function(element) {
    element = $(element);
    try {
      element.focus();
      if (element.select && (element.tagName.toLowerCase() != 'input' ||
          !['button', 'reset', 'submit'].include(element.type)))
        element.select();
    } catch (e) { }
    return element;
  }

  相关解决方案