`

Prototype1.5.1.1代码注释(三)

阅读更多
/*用的最多的怕就是这个方法了吧*/
function $(element) {
  if (arguments.length > 1) {
    for (var i = 0, elements = [], length = arguments.length; i < length; i++)
      elements.push($(arguments[i]));
    return elements;
  }
  if (typeof element == 'string')
    element = document.getElementById(element);
  return Element.extend(element);
}

/*定义getElementByClassName方法*/
if (Prototype.BrowserFeatures.XPath) {
  document._getElementsByXPath = function(expression, parentElement) {
    var results = [];
    var query = document.evaluate(expression, $(parentElement) || document,
      null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
    for (var i = 0, length = query.snapshotLength; i < length; i++)
      results.push(query.snapshotItem(i));
    return results;
  };

  document.getElementsByClassName = function(className, parentElement) {
    var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]";
    return document._getElementsByXPath(q, parentElement);
  }

} else document.getElementsByClassName = function(className, parentElement) {
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
  var elements = [], child, pattern = new RegExp("(^|\\s)" + className + "(\\s|$)");
  for (var i = 0, length = children.length; i < length; i++) {
    child = children[i];
    var elementClassName = child.className;
    if (elementClassName.length == 0) continue;
    if (elementClassName == className || elementClassName.match(pattern))
      elements.push(Element.extend(child));
  }
  return elements;
};

/*--------------------------------------------------------------------------*/

if (!window.Element) var Element = {};

Element.extend = function(element) {
  var F = Prototype.BrowserFeatures;
  /*
    element的nodeType属性:
        1 Element node. 
        3 Text node. 
  */
  /*
    只有在element
        1.包含tagName属性
        2.element不是text node
        3.element不包含_extended属性
        4.当前浏览器不是IE
        5.且element元素不是window对象
    的情况下才会继续执行
  */
  if (!element || !element.tagName || element.nodeType == 3 ||
   element._extended || F.SpecificElementExtensions || element == window)
    return element;

  var methods = {}, tagName = element.tagName, cache = Element.extend.cache,
   T = Element.Methods.ByTag;

  // extend methods for all tags ( Safari doesn't need this)
  /*从我测试的结果来看F.ElementExtensions在firefox上同样是true*/
  if (!F.ElementExtensions) {
    Object.extend(methods, Element.Methods),
    Object.extend(methods, Element.Methods.Simulated);
  }

  // extend methods for specific tags
  if (T[tagName]) Object.extend(methods, T[tagName]);

  for (var property in methods) {
    var value = methods[property];
    if (typeof value == 'function' && !(property in element))
      element[property] = cache.findOrStore(value);
  }
  /*这里定义了一把element._extended,飘逸啊。。。。完全一头雾水*/  
  element._extended = Prototype.emptyFunction;
  return element;
};

Element.extend.cache = {
  findOrStore: function(value) {
    return this[value] = this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
  }
};

/*定义了一些通用的methods
*/
Element.Methods = {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function(element) {
    element = $(element);
    Element[Element.visible(element) ? 'hide' : 'show'](element);
    return element;
  },

  hide: function(element) {
    $(element).style.display = 'none';
    return element;
  },

  show: function(element) {
    $(element).style.display = '';
    return element;
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
    return element;
  },

  update: function(element, html) {
    html = typeof html == 'undefined' ? '' : html.toString();
    $(element).innerHTML = html.stripScripts();
    /*这一步不太理解*/
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  replace: function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    /*IE里面定义了outerHTML而Firefox中没有这个属性*/
    if (element.outerHTML) {
      element.outerHTML = html.stripScripts();
    } else {
      /*取得包含element的document对象,并调用它的createRange方法*/
      /*Creates a TextRange object from the current text selection, or a controlRange collection from a control selection*/
      /*
      用Range进行选择,用selectNode()或者selectNodeContents()方法,这两个方法只有一个接收参数,一个DOM节点。
        selectNode()方法选择全部节点,包括它的孩子,而selectNodeContents()选择的节点只是它的孩子。如<p id="p1"><b>Hello</b> World</p>
        <script>
        var oRange1 = document.createRange();
        var oRange2 = document.createRange();
        var oP1 = document.getElementById("p1");
        oRange1.selectNode(oP1);
        oRange2.selectNodeContents(oP1);
        </script>
        使用selectNode方法,选择的部分如下:
        <p id="p1"><b>Hello</b> World</p>
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        而使用selectNodeContents方法,选择的部分如下:
        <p id="p1"><b>Hello</b> World</p>
                   ~~~~~~~~~~~~
      关于Range对象更多的说明,可以参考http://hi.baidu.com/llaa27/blog/item/2ea8f1f49fcb81daf2d385db.html
      */
      var range = element.ownerDocument.createRange();
      range.selectNodeContents(element);
      element.parentNode.replaceChild(
        range.createContextualFragment(html.stripScripts()), element);
    }
    setTimeout(function() {html.evalScripts()}, 10);
    return element;
  },

  inspect: function(element) {
    element = $(element);
    var result = '<' + element.tagName.toLowerCase();
    $H({'id': 'id', 'className': 'class'}).each(function(pair) {
      /*property对应DOM中对应的属性名
      attribute对应实际HTML文件中书写的代码
      举一个例子:
      <div id="content" class="div_content"></div>
      property       attribute
      ---------------------------
      "id"             "id"
      "className"     "class"
      ---------------------------
      */
      var property = pair.first(), attribute = pair.last();
      var value = (element[property] || '').toString();
      if (value) result += ' ' + attribute + '=' + value.inspect(true);
    });
    return result + '>';
  },
  /*
    <ul id="fruits">
      <li id="apples">
        <ul id="list-of-apples">
          <li id="golden-delicious"><p>Golden Delicious</p></li>
          <li id="mutsu">Mutsu</li>
          <li id="mcintosh">McIntosh</li>
          <li id="ida-red">Ida Red</li>
        </ul>
      </li>
    </ul>

    $('fruits').recursivelyCollect('firstChild');
    -> [li#apples, ul#list-of-apples, li#golden-delicious, p]
  */
  /*注:不包含text node*/
  recursivelyCollect: function(element, property) {
    element = $(element);
    var elements = [];
    while (element = element[property])
      if (element.nodeType == 1)
        elements.push(Element.extend(element));
    return elements;
  },

  /*收集某个元素的祖先列表*/
  /*注:不包含text node*/
  ancestors: function(element) {
    return $(element).recursivelyCollect('parentNode');
  },

  /*收集某个元素的子孙元素列表*/
  /*注:不包含text node*/
  descendants: function(element) {
    return $A($(element).getElementsByTagName('*')).each(Element.extend);
  },

  /*element的第一个子节点*/
  /*注:不包含text node*/
  firstDescendant: function(element) {
    element = $(element).firstChild;
    while (element && element.nodeType != 1) element = element.nextSibling;
    return $(element);
  },

  /*取得element所有子节点元素的列表*/
  /*
    <div id="australopithecus">
      <div id="homo-herectus">
        <div id="homo-neanderthalensis"></div>
        <div id="homo-sapiens"></div>
      </div>
    </div>

    $('australopithecus').immediateDescendants();
    -> [div#homo-herectus]

    $('homo-herectus').immediateDescendants();
    -> [div#homo-neanderthalensis, div#homo-sapiens]

    $('homo-sapiens').immediateDescendants();
    -> []
    */
    /*注:不包含text node*/
  immediateDescendants: function(element) {
    if (!(element = $(element).firstChild)) return [];
    while (element && element.nodeType != 1) element = element.nextSibling;
    if (element) return [element].concat($(element).nextSiblings());
    return [];
  },

  /*取得element所有的previous兄弟节点*/
  previousSiblings: function(element) {
    return $(element).recursivelyCollect('previousSibling');
  },

  /*取得element所有的next兄弟节点*/
  nextSiblings: function(element) {
    return $(element).recursivelyCollect('nextSibling');
  },

  /*element所有的兄弟节点*/
  siblings: function(element) {
    element = $(element);
    return element.previousSiblings().reverse().concat(element.nextSiblings());
  },

  match: function(element, selector) {
    if (typeof selector == 'string')
      selector = new Selector(selector);
    return selector.match($(element));
  },

  up: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(element.parentNode);
    var ancestors = element.ancestors();
    return expression ? Selector.findElement(ancestors, expression, index) :
      ancestors[index || 0];
  },

  down: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return element.firstDescendant();
    var descendants = element.descendants();
    return expression ? Selector.findElement(descendants, expression, index) :
      descendants[index || 0];
  },

  previous: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
    var previousSiblings = element.previousSiblings();
    return expression ? Selector.findElement(previousSiblings, expression, index) :
      previousSiblings[index || 0];
  },

  next: function(element, expression, index) {
    element = $(element);
    if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
    var nextSiblings = element.nextSiblings();
    return expression ? Selector.findElement(nextSiblings, expression, index) :
      nextSiblings[index || 0];
  },

  getElementsBySelector: function() {
    var args = $A(arguments), element = $(args.shift());
    return Selector.findChildElements(element, args);
  },

  getElementsByClassName: function(element, className) {
    return document.getElementsByClassName(className, element);
  },

  
  /*可供查询的属性有:
  colspan,
  rowspan,
  valign,
  datetime,
  accesskey,
  tablindex,
  enctype,
  maxlength,
  readonly,
  longdesc,
  style,
  title,
  href,
  src,
  type,
  disabled,
  checked,
  readonly,
  multiple
  如果这里面没有的话可以直接调用Element._attributeTranslations.values["_getAttr"](ele,attr)
  也可以用Element._attributeTranslations.values["_flag"](ele,attr)来判断某个element是否包含指定属性
  */
  readAttribute: function(element, name) {
    element = $(element);
    if (Prototype.Browser.IE) {
      if (!element.attributes) return null;
      var t = Element._attributeTranslations;
      if (t.values[name]) return t.values[name](element, name);
      if (t.names[name])  name = t.names[name];
      var attribute = element.attributes[name];
      return attribute ? attribute.nodeValue : null;
    }
    return element.getAttribute(name);
  },

  getHeight: function(element) {
    return $(element).getDimensions().height;
  },

  getWidth: function(element) {
    return $(element).getDimensions().width;
  },

  classNames: function(element) {
    return new Element.ClassNames(element);
  },

  /*判断element是否有指定的className*/
  /*判断前element.className中前后的空格将会被忽略*/
  hasClassName: function(element, className) {
    if (!(element = $(element))) return;
    var elementClassName = element.className;
    if (elementClassName.length == 0) return false;
    if (elementClassName == className ||
        elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
      return true;
    return false;
  },

  addClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).add(className);
    return element;
  },

  removeClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element).remove(className);
    return element;
  },

  toggleClassName: function(element, className) {
    if (!(element = $(element))) return;
    Element.classNames(element)[element.hasClassName(className) ? 'remove' : 'add'](className);
    return element;
  },

  observe: function() {
    Event.observe.apply(Event, arguments);
    return $A(arguments).first();
  },

  stopObserving: function() {
    Event.stopObserving.apply(Event, arguments);
    return $A(arguments).first();
  },

  // removes whitespace-only text node children
  cleanWhitespace: function(element) {
    element = $(element);
    var node = element.firstChild;
    while (node) {
      var nextNode = node.nextSibling;
      if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
        element.removeChild(node);
      node = nextNode;
    }
    return element;
  },

  /*判断element的innerHTML是否为空*/
  empty: function(element) {
    return $(element).innerHTML.blank();
  },

  /*判断element是否是ancestor的子孙节点*/
  descendantOf: function(element, ancestor) {
    element = $(element), ancestor = $(ancestor);
    while (element = element.parentNode)
      if (element == ancestor) return true;
    return false;
  },

  /*网页卷动到指定元素的位置*/
  scrollTo: function(element) {
    element = $(element);
    var pos = Position.cumulativeOffset(element);
    window.scrollTo(pos[0], pos[1]);
    return element;
  },
 
  
  getStyle: function(element, style) {
    element = $(element);
    style = style == 'float' ? 'cssFloat' : style.camelize();
    var value = element.style[style];
    if (!value) {
      var css = document.defaultView.getComputedStyle(element, null);
      value = css ? css[style] : null;
    }
    if (style == 'opacity') return value ? parseFloat(value) : 1.0;
    return value == 'auto' ? null : value;
  },

  getOpacity: function(element) {
    return $(element).getStyle('opacity');
  },

  setStyle: function(element, styles, camelized) {
    element = $(element);
    var elementStyle = element.style;

    for (var property in styles)
      if (property == 'opacity') element.setOpacity(styles[property])
      else
        elementStyle[(property == 'float' || property == 'cssFloat') ?
          (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') :
          (camelized ? property : property.camelize())] = styles[property];

    return element;
  },

  /*设置透明度*/
  setOpacity: function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1 || value === '') ? '' :
      (value < 0.00001) ? 0 : value;
    return element;
  },

  /*取得DOM元素的大小*/
  getDimensions: function(element) {
    element = $(element);
    var display = $(element).getStyle('display');
    if (display != 'none' && display != null) // Safari bug
      return {width: element.offsetWidth, height: element.offsetHeight};

    // All *Width and *Height properties give 0 on elements with display none,
    // so enable the element temporarily
    var els = element.style;
    var originalVisibility = els.visibility;
    var originalPosition = els.position;
    var originalDisplay = els.display;
    els.visibility = 'hidden';
    els.position = 'absolute';
    els.display = 'block';
    var originalWidth = element.clientWidth;
    var originalHeight = element.clientHeight;
    els.display = originalDisplay;
    els.position = originalPosition;
    els.visibility = originalVisibility;
    return {width: originalWidth, height: originalHeight};
  },

  /*把一个元素的postion从static改为relative*/
  makePositioned: function(element) {
    element = $(element);
    var pos = Element.getStyle(element, 'position');
    if (pos == 'static' || !pos) {
      //这里留下一个记号,表示此元素曾经使用过makePositioned方法
      element._madePositioned = true;
      element.style.position = 'relative';
      // Opera returns the offset relative to the positioning context, when an
      // element is position relative but top and left have not been defined
      if (window.opera) {
        element.style.top = 0;
        element.style.left = 0;
      }
    }
    return element;
  },

  undoPositioned: function(element) {
    element = $(element);
    //必须先makePositioned之后才能undoPositioned
    if (element._madePositioned) {
      //销毁makePositioned的证据
      element._madePositioned = undefined;
      element.style.position =
        element.style.top =
        element.style.left =
        element.style.bottom =
        element.style.right = '';
    }
    return element;
  },

  //设置某个元素的overflow属性为hidden,也就是说超出的地方会被隐藏
  makeClipping: function(element) {
    element = $(element);
    if (element._overflow) return element;
    element._overflow = element.style.overflow || 'auto';
    if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden')
      element.style.overflow = 'hidden';
    return element;
  },

  //如果对某个元素调用过makeClipping,调用undoClipping会设置overflow属性回auto
  undoClipping: function(element) {
    element = $(element);
    if (!element._overflow) return element;
    element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
    element._overflow = null;
    return element;
  }
};

Object.extend(Element.Methods, {
  childOf: Element.Methods.descendantOf,
  childElements: Element.Methods.immediateDescendants
});

if (Prototype.Browser.Opera) {
  Element.Methods._getStyle = Element.Methods.getStyle;
  Element.Methods.getStyle = function(element, style) {
    switch(style) {
      case 'left':
      case 'top':
      case 'right':
      case 'bottom':
        if (Element._getStyle(element, 'position') == 'static') return null;
      default: return Element._getStyle(element, style);
    }
  };
}
else if (Prototype.Browser.IE) {
  Element.Methods.getStyle = function(element, style) {
    element = $(element);
    style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
    var value = element.style[style];
    if (!value && element.currentStyle) value = element.currentStyle[style];

    if (style == 'opacity') {
      if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
        if (value[1]) return parseFloat(value[1]) / 100;
      return 1.0;
    }

    if (value == 'auto') {
      if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
        return element['offset'+style.capitalize()] + 'px';
      return null;
    }
    return value;
  };

  Element.Methods.setOpacity = function(element, value) {
    element = $(element);
    var filter = element.getStyle('filter'), style = element.style;
    if (value == 1 || value === '') {
      style.filter = filter.replace(/alpha\([^\)]*\)/gi,'');
      return element;
    } else if (value < 0.00001) value = 0;
    style.filter = filter.replace(/alpha\([^\)]*\)/gi, '') +
      'alpha(opacity=' + (value * 100) + ')';
    return element;
  };

  // IE is missing .innerHTML support for TABLE-related elements
  // 因为IE在处理THEAD,TBODY,TR,TD的时候没有.innerHTML属性,所以只能采用appendChild的方式来曲线救国
  // 首先创建一个包含Table元素的DIV,将要替换的html添加到div的table中,这样就可以利用table以node的方法
  // 读取要添加的html元素,再把这些node添加到element中去
  Element.Methods.update = function(element, html) {
    element = $(element);
    html = typeof html == 'undefined' ? '' : html.toString();
    var tagName = element.tagName.toUpperCase();
    if (['THEAD','TBODY','TR','TD'].include(tagName)) {
      var div = document.createElement('div');
      switch (tagName) {
        case 'THEAD':
        case 'TBODY':
          div.innerHTML = '<table><tbody>' +  html.stripScripts() + '</tbody></table>';
          depth = 2;
          break;
        case 'TR':
          div.innerHTML = '<table><tbody><tr>' +  html.stripScripts() + '</tr></tbody></table>';
          depth = 3;
          break;
        case 'TD':
          div.innerHTML = '<table><tbody><tr><td>' +  html.stripScripts() + '</td></tr></tbody></table>';
          depth = 4;
      }
      $A(element.childNodes).each(function(node) { element.removeChild(node) });
      depth.times(function() { div = div.firstChild });
      $A(div.childNodes).each(function(node) { element.appendChild(node) });
    } else {
      element.innerHTML = html.stripScripts();
    }
    setTimeout(function() { html.evalScripts() }, 10);
    return element;
  }
}
else if (Prototype.Browser.Gecko) {
  Element.Methods.setOpacity = function(element, value) {
    element = $(element);
    element.style.opacity = (value == 1) ? 0.999999 :
      (value === '') ? '' : (value < 0.00001) ? 0 : value;
    return element;
  };
}

/*关于getAttribute说明
    Retrieves the value of the specified attribute. 

    Syntax

    vAttrValue = object.getAttribute(sAttrName [, iFlags])
    Parameters

    sAttrName Required. String that specifies the name of the attribute. 
    iFlags Optional. Integer that specifies one or more of the following flags:
    0 Default. Performs a property search that is not case-sensitive, and returns an interpolated value if the property is found. 
    1 Performs a case-sensitive property search. To find a match, the uppercase and lowercase letters in sAttrName must exactly match those in the attribute name. If the iFlags parameter for getAttribute is set to 1 and this option is set to 0 (default), the specified property name might not be found. 
    2 Returns the value exactly as it was set in script or in the source document. 
     

    Return Value
    Variant that returns a String, number, or Boolean value as defined by the attribute. If the attribute is not present, this method returns null. 
*/
Element._attributeTranslations = {
  names: {
    colspan:   "colSpan",
    rowspan:   "rowSpan",
    valign:    "vAlign",
    datetime:  "dateTime",
    accesskey: "accessKey",
    tabindex:  "tabIndex",
    enctype:   "encType",
    maxlength: "maxLength",
    readonly:  "readOnly",
    longdesc:  "longDesc"
  },
  values: {
    //取得attribute node
    _getAttr: function(element, attribute) {
      return element.getAttribute(attribute, 2);
    },
    //判断是否包含某个attribute
    _flag: function(element, attribute) {
      return $(element).hasAttribute(attribute) ? attribute : null;
    },
    //获得DOM中style属性的内容
    style: function(element) {
      return element.style.cssText.toLowerCase();
    },
    //获得DOM元素title属性的内用
    title: function(element) {
      var node = element.getAttributeNode('title');
      return node.specified ? node.nodeValue : null;
    }
  }
};

/*给Element._attributeTranslations.values添加了7个方法
之所以写在外面完全是为了DRY吧
href,
src,
type,
disabled,
checked,
readonly,
multiple
这样话基本上所有的属性都覆盖到了,除了一些不常用的,例如dir,lang等
*/
(function() {
  Object.extend(this, {
    href: this._getAttr,
    src:  this._getAttr,
    type: this._getAttr,
    disabled: this._flag,
    checked:  this._flag,
    readonly: this._flag,
    multiple: this._flag
  });
}).call(Element._attributeTranslations.values);

/* getAttributeNode方法说明
    Retrieves an attribute object referenced by the attribute.name property.

    Syntax

    oAttribute = object.getAttributeNode(sName)
    Parameters

    sName Required. String that specifies the name property of the requested attribute object. 

    Return Value

    Returns a reference to an attribute object.
*/
Element.Methods.Simulated = {
  hasAttribute: function(element, attribute) {
    var t = Element._attributeTranslations, node;
    attribute = t.names[attribute] || attribute;
    node = $(element).getAttributeNode(attribute);
    return node && node.specified;
  }
};

Element.Methods.ByTag = {};

Object.extend(Element, Element.Methods);

if (!Prototype.BrowserFeatures.ElementExtensions &&
 document.createElement('div').__proto__) {
  window.HTMLElement = {};
  window.HTMLElement.prototype = document.createElement('div').__proto__;
  Prototype.BrowserFeatures.ElementExtensions = true;
}

Element.hasAttribute = function(element, attribute) {
  if (element.hasAttribute) return element.hasAttribute(attribute);
  return Element.Methods.Simulated.hasAttribute(element, attribute);
};

Element.addMethods = function(methods) {
  var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;

  if (!methods) {
    Object.extend(Form, Form.Methods);
    Object.extend(Form.Element, Form.Element.Methods);
    Object.extend(Element.Methods.ByTag, {
    //在Element.Methods.ByTag下产生四个命名空间,各自下面有不同标签对应的方法
      "FORM":     Object.clone(Form.Methods),
      "INPUT":    Object.clone(Form.Element.Methods),
      "SELECT":   Object.clone(Form.Element.Methods),
      "TEXTAREA": Object.clone(Form.Element.Methods)
    });
  }

  if (arguments.length == 2) {
    var tagName = methods;
    methods = arguments[1];
  }

  if (!tagName) Object.extend(Element.Methods, methods || {});
  else {
    if (tagName.constructor == Array) tagName.each(extend);
    else extend(tagName);
  }

  function extend(tagName) {
    tagName = tagName.toUpperCase();
    if (!Element.Methods.ByTag[tagName])
      Element.Methods.ByTag[tagName] = {};
    Object.extend(Element.Methods.ByTag[tagName], methods);
  }

  function copy(methods, destination, onlyIfAbsent) {
    onlyIfAbsent = onlyIfAbsent || false;
    var cache = Element.extend.cache;
    for (var property in methods) {
      var value = methods[property];
      if (!onlyIfAbsent || !(property in destination))
        destination[property] = cache.findOrStore(value);
    }
  }

  function findDOMClass(tagName) {
    var klass;
    var trans = {
      "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
      "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
      "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
      "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
      "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
      "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
      "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
      "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
      "FrameSet", "IFRAME": "IFrame"
    };
    if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
    if (window[klass]) return window[klass];
    klass = 'HTML' + tagName + 'Element';
    if (window[klass]) return window[klass];
    klass = 'HTML' + tagName.capitalize() + 'Element';
    if (window[klass]) return window[klass];

    window[klass] = {};
    window[klass].prototype = document.createElement(tagName).__proto__;
    return window[klass];
  }

  if (F.ElementExtensions) {
    copy(Element.Methods, HTMLElement.prototype);
    copy(Element.Methods.Simulated, HTMLElement.prototype, true);
  }

  if (F.SpecificElementExtensions) {
    for (var tag in Element.Methods.ByTag) {
      var klass = findDOMClass(tag);
      if (typeof klass == "undefined") continue;
      copy(T[tag], klass.prototype);
    }
  }

  Object.extend(Element, Element.Methods);
  delete Element.ByTag;
};

var Toggle = { display: Element.toggle };

/*--------------------------------------------------------------------------*/

Abstract.Insertion = function(adjacency) {
  this.adjacency = adjacency;
}

/*
    Inserts the given HTML text into the element at the location.

    Syntax

    object.insertAdjacentHTML(sWhere, sText)
    Parameters

    sWhere Required. String that specifies where to insert the HTML text, using one of the following values: beforeBegin Inserts sText immediately before the object. 
    afterBegin Inserts sText after the start of the object but before all other content in the object. 
    beforeEnd Inserts sText immediately before the end of the object but after all other content in the object. 
    afterEnd Inserts sText immediately after the end of the object. 
     
    sText Required. String that specifies the HTML text to insert. The string can be a combination of text and HTML tags. This must be well-formed, valid HTML or this method will fail. 
*/
Abstract.Insertion.prototype = {
  initialize: function(element, content) {
    this.element = $(element);
    this.content = content.stripScripts();

    if (this.adjacency && this.element.insertAdjacentHTML) {
      try {
        this.element.insertAdjacentHTML(this.adjacency, this.content);
      } catch (e) {
        var tagName = this.element.tagName.toUpperCase();
        // 在TBODY和TR前插入对象与众不同
        if (['TBODY', 'TR'].include(tagName)) {
          this.insertContent(this.contentFromAnonymousTable());
        } else {
          throw e;
        }
      }
    } else {
      this.range = this.element.ownerDocument.createRange();
      if (this.initializeRange) this.initializeRange();
      this.insertContent([this.range.createContextualFragment(this.content)]);
    }

    setTimeout(function() {content.evalScripts()}, 10);
  },

  // 构造一个匿名table,然后把指定的内容插到<tbody></tbody>之间
  // 最后返回一个代表指定内容的node对象
  contentFromAnonymousTable: function() {
    var div = document.createElement('div');
    div.innerHTML = '<table><tbody>' + this.content + '</tbody></table>';
    return $A(div.childNodes[0].childNodes[0].childNodes);
  }
}

var Insertion = new Object();

Insertion.Before = Class.create();
Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), {
  initializeRange: function() {
    this.range.setStartBefore(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment, this.element);
    }).bind(this));
  }
});

Insertion.Top = Class.create();
Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(true);
  },

  insertContent: function(fragments) {
    fragments.reverse(false).each((function(fragment) {
      this.element.insertBefore(fragment, this.element.firstChild);
    }).bind(this));
  }
});

Insertion.Bottom = Class.create();
Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), {
  initializeRange: function() {
    this.range.selectNodeContents(this.element);
    this.range.collapse(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.appendChild(fragment);
    }).bind(this));
  }
});

Insertion.After = Class.create();
Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
  initializeRange: function() {
    this.range.setStartAfter(this.element);
  },

  insertContent: function(fragments) {
    fragments.each((function(fragment) {
      this.element.parentNode.insertBefore(fragment,
        this.element.nextSibling);
    }).bind(this));
  }
});

/*--------------------------------------------------------------------------*/

Element.ClassNames = Class.create();
Element.ClassNames.prototype = {
  initialize: function(element) {
    this.element = $(element);
  },

  _each: function(iterator) {
    this.element.className.split(/\s+/).select(function(name) {
      return name.length > 0;
    })._each(iterator);
  },

  set: function(className) {
    this.element.className = className;
  },

  add: function(classNameToAdd) {
    if (this.include(classNameToAdd)) return;
    this.set($A(this).concat(classNameToAdd).join(' '));
  },

  remove: function(classNameToRemove) {
    if (!this.include(classNameToRemove)) return;
    this.set($A(this).without(classNameToRemove).join(' '));
  },

  toString: function() {
    return $A(this).join(' ');
  }
};
 
分享到:
评论

相关推荐

    Really easy field validation with Prototype 1.5.4.1 中文修改版

    所做的更改: &lt;br&gt;1、prototype.js 版本更新为 v1.5.1.1 &lt;br&gt;2、effects.js 版本更新为 v1.7.1_beta3 &lt;br&gt;3、所有校验错误提示信息均修改为中文,提供UTF-8和GB18030两种编码的版本 &lt;br&gt;4、增加"YYYY-MM...

    prototype.js

    其中里面包含了prototype1.5 prototype1.5.1 prototype1.5.1.1 prototype1.5.1.2 prototype1.6.0。五个版本。 http://blog.csdn.net/boat1980/archive/2008/04/10/2278259.aspx这个连接有1.5.1.1代码的注释。

    Prototype.js

    Prototype.js (ver:1.5.1.1) Prototype.js 帮助(ver:1.5.1)英文PDF Prototype.js 帮助(ver:1.4)中文CHM Prototype.js 帮助(ver:1.4)中文PDF

    Prototype 1.5 中文手册.rar

    - `Prototype.extend`:此方法允许向对象添加新的属性或方法,实现对象的扩展。 - `Event`模块:提供事件处理相关的函数,如`observe`、`stopObserving`等,便于事件监听和移除。 3. Ajax功能: Prototype库的...

    Prototype 1.5 中文文档 chm

    Prototype 最新的1.5 版中文文档,chm格式,很多人都在找。Prototype 是一个非常优秀的javascript基础类库,可以很好的支持Ajax,国外有多个基于此类库的扩展,这是最新的1.5中文文档,AJAX编程必备手册。

    prototype中文手册及API

    prototype中文手册及API --------------------- prototype.js(1.5.1.1) prototype中文手册 prototype.chm

    prototype-1.6.0.3.js+prototype1.4 、1.5中文手册+prototype1.6英文手册

    接下来是三个CHM文件,分别是Prototype的1.4、1.5和1.6版本的手册。这些手册是开发者的重要参考资料,详细介绍了每个版本的功能、API用法以及示例代码。在1.4中文手册中,你可以找到关于`Element`、`Selector`、`...

    prototype_1.7.3.js 最新版本

    《prototype_1.7.3.js:JavaScript框架的里程碑》 在JavaScript的世界里,Prototype库是一个不可...无论你是新手还是经验丰富的开发者,掌握Prototype.js都能让你在Web开发中如虎添翼,进一步提升代码质量和开发效率。

    prototype.js 源码解读, 中文帮助文档

    开发者网站: http://prototype.conio.net/ prototype学习资料包括: prototype14参考 prototype 1.3 源码解读.txt prototype 1.5 参考图 prototype 1.5pre1.js prototype 1.4.js

    prototype1.6.0.2.js

    prototype1.6.0.2

    prototype 1.6.0.2.js+使用DEMO例子

    通过提供的DEMO例子,开发者可以直观地看到Prototype在实际项目中的应用,理解如何将这些工具和方法融入到自己的代码中。实践中,可能包括创建动态页面、实现异步数据交互、优化DOM操作等方面。 总的来说,这个...

    prototype1.5中文说明

    通过阅读`Prototype.doc`文档,你可以深入了解Prototype库的每个细节,学习如何有效地利用这些功能来构建高效、动态的Web应用程序。无论你是JavaScript新手还是经验丰富的开发者,Prototype 1.5RC2都是一个值得学习...

    prototype 1.6中文手册 chm+prototype 1.6.js源码 最新版

    包含的"prototype.js"文件是Prototype 1.6.0的源代码,这对于开发者来说是一份宝贵的参考资料。通过阅读源码,开发者可以直接了解每个函数的实现细节,理解其工作原理,从而更好地应用到自己的项目中。源码中的注释...

    基于ASP的风铃ASP文件共享系统(多文件上传) v1.5.zip

    此外,可能还会有第三方库如JQuery或Prototype来增强前端交互效果。 【维护和升级】 对于这样的系统,持续的维护和升级是必要的。这可能涉及修复已知的bug,增加新的特性,如支持更多格式的文件,或改进用户界面。...

    prototype1.5

    《Prototype 1.5:JavaScript 引领Ajax技术新里程》 Prototype 1.5,作为JavaScript库的一个重要里程碑,为Web开发引入了强大的功能和灵活性,尤其在处理Ajax(异步JavaScript和XML)交互方面。这个版本的发布极大...

    prototype.js 1.6中文手册、prototype.js 1.6英文手册、

    **Prototype.js 1.6 知识点详解** Prototype.js 是一个开源的JavaScript库,它扩展了JavaScript语言,为开发者提供了许多便利的功能,特别是在对象操作、DOM操作和事件处理方面。1.6版本是该库的一个重要里程碑,...

    prototype1.6.1 .js

    prototype1.6.1 .js 时下流行的前端开发javascript类库

    使用Prototype框架.pdfprototype源码分析.doc

    例解Prototype框架.doc 第21章__使用Prototype框架.pdf Prototype源码注释版.pdf proprototype源码分析.doc totype_1.3_源码解读.txt

    Prototype.and.script.aculo.us.Dec.2007.pdf

    #### 1.1 Prototype框架 Prototype是最早的JavaScript库之一,它简化了DOM操作,提供了一套强大的功能,如AJAX支持、事件处理、DOM遍历和修改等。它通过扩展原生JavaScript对象(如Array和String),使得开发人员...

    prototype1.6.0.3.rar

    《Prototype JavaScript 框架详解:以 prototype1.6.0.3.rar 文件为中心》 在Web开发领域,JavaScript框架的出现极大地提升了开发效率和代码质量。Prototype JavaScript框架,作为一个历史悠久且广泛使用的库,为...

Global site tag (gtag.js) - Google Analytics