![]() ![]() |
websvn |
Subversion Repositories: |
Compare with Previous - Blame - Download
<?xml version="1.0" encoding="ISO-8859-1"?><bindings xmlns="http://www.mozilla.org/xbl" xmlns:html="http://www.w3.org/1999/xhtml"><!--moz-behaviors.xml - version 1.1 (pre-release) (2005/05/15)Copyright 2004-2005, Dean EdwardsWeb: http://dean.edwards.name/moz-behaviors/This software is licensed under the CC-GNU LGPLWeb: http://creativecommons.org/licenses/LGPL/2.1/--><!--=======================================================================TO DO=======================================================================hideFocusfix CSSStyleDeclaration pixel*.__defineGetter__behaviors FAQtest Event.returnValue=======================================================================DONE=======================================================================styleFloatallow upper case tags/attributessupport for external JS filesbetter support for oncontentready/ondocumentreadysupport for multiple behaviors in cssActiveXObject=======================================================================--><!-- add a behavior through css --><binding id="behavior" extends="#-moz-behaviors"><implementation><constructor><![CDATA[addBehavior(0);]]></constructor></implementation></binding><binding id="-moz-behaviors" extends="#-moz-ie"><implementation><constructor><![CDATA[if(!this.addBehavior){// ------------------------------------------------------------------// htc extensions for mozilla// ------------------------------------------------------------------/* here we define the addBehavior/removeBehavior methods for an elementthese methods are used to add and remove all dhtml behaviors*/var _cookie = -1; // no support for removeBehavior yet// implement the addBehavior method for all elementsElement.prototype.addBehavior = function(_url) {try {// calling this method with the first argument as zero// initialises the object's behaviorsif (_url === 0) {// grab the htc's url from the css settingvar $binding = getComputedStyle(this, null).getPropertyValue("-moz-binding");$binding = $binding.replace(/^url\(([^)]*)\)$/, "$1").split("#");if ($binding) {var $path = $binding[0].replace(/[^\/]+$/, "");// support multiple behaviorsvar $htcs = $binding[1].split("|");var i = $htcs.length;while (i--) this.addBehavior($path + $htcs[i]);}}if (!_url) return;// check the cacheif (!document.behaviorUrns[_url]) {// constantsvar $SEPARATOR = ";";function _getTagName($node) {var $tagName = $node.tagName.toLowerCase();// this fixes a bug(?) in Mozilla 1.6b that includes the// namespace prefix in the tagNamereturn $tagName.slice($tagName.indexOf(":") + 1);};function _getAttribute($node, $attribute) {return $node.getAttribute($attribute) || $node.getAttribute($attribute.toUpperCase());};// this function converts elements in a behavior to a program// declaration, for example:// <public:attach for="window" event="onload" handler="init"/>// becomes:// window.addEventListener("load", init);function _asDeclaration($behaviorNode) {switch (_getTagName($behaviorNode)) {case "event":var id = _getAttribute($behaviorNode, "id");return (id) ? "var " + id + "={fire:function(event){element.fireEvent('" +_getAttribute($behaviorNode, "name") + "',event)}}" : "";case "property":var $name = _getAttribute($behaviorNode, "name");var $get = _getAttribute($behaviorNode, "get") || "function(){return getAttribute('" +$name + "')}";$get = "__defineGetter__('" + $name + "'," + $get + ")";var $put = _getAttribute($behaviorNode, "put") || "";if ($put) $put += ".call(element,value);";$put = "function(value){" + $put + "setAttribute('" + $name + "',value)}";$put = "__defineSetter__('" + $name + "'," + $put + ")";return $get + $SEPARATOR + $put;case "method":return "element." + _getAttribute($behaviorNode, "name") + "=" + _getAttribute($behaviorNode, "name");case "attach":var $handler = _getAttribute($behaviorNode, "handler") || "";$handler += ($handler) ? "()" : _getAttribute($behaviorNode, "onevent");$handler = "function(event){window.event=event;return " + $handler + "}";var $event = _getAttribute($behaviorNode, "event");switch ($event) {case "oncontentready": return "window.setTimeout(" + $handler + ",1)";case "ondocumentready": return "document.behaviorUrns.__private.push(" + $handler + ")";}return (_getAttribute($behaviorNode, "for")||"element") + ".addEventListener('" + $event.slice(2) + "'," + $handler + ",false)";case "defaults":// not implementeddefault:return "";}};function _asDefault($node) {return (_getAttribute($node, "put")) ? ";var __tmp=getAttribute('" + _getAttribute($node, "name") + "')||" +(_getAttribute($node, "value") || "null") +";if(__tmp!=null)element['" + _getAttribute($node, "name") + "']=__tmp" : "";};// extract the body of a functionfunction _getFunctionBody($function) {with (String($function)) return slice(indexOf("{") + 1, lastIndexOf("}"));};// behaviors are defined as xml documents, so we can use// the http request object to load them and the dom parser// object to parse them into a dom treevar _httpRequest = new XMLHttpRequest;function _loadFile($url) {try {// load the behavior_httpRequest.open("GET", $url, false);_httpRequest.send(null);return _httpRequest.responseText;} catch ($ignore) {// ignore (but don't crash)}};// analyse the dom tree, build the interface and create the scriptvar _declarations = [];var _defaults = "";var _script = "";function _load() {// build a dom representation of the loaded xml documentvar $dom = (new DOMParser).parseFromString(_loadFile(_url), "text/xml");var $childNodes = $dom.documentElement.childNodes, $node;for (var i = 0; ( $node = $childNodes[i]); i++) {if ($node.nodeType == Node.ELEMENT_NODE) {if (_getTagName($node) == "script") {var $src = _getAttribute($node, "src");if ($src) {_script += _loadFile($src);} else {// build the script from the text nodes of the script elementfor (var j = 0; j < $node.childNodes.length; j++)_script += $node.childNodes[j].nodeValue;}} else {// convert the dom node representation of a// <public:declaration/> to a javascript statement// and store it in our declarations collection_declarations.push(_asDeclaration($node));if (_getTagName($node) == "property") {_defaults += _asDefault($node);}}}}_defaults += ";delete __tmp";};_load();// we've finished collecting interface declarations.// they are now held as an array of strings.// build a function from the script and extract the function body// this has the effect of formatting the script (removing comments etc)_script = _getFunctionBody(new Function(_script));// support: new ActiveXObjectvar $ACTIVEX = /\bnew\s+ActiveXObject\s*\(\s*(["'])\w\.XMLHTTP\1\s*\)/gi;_script = _script.replace($ACTIVEX, "new XMLHttpRequest()");// begin: annoying parse of script to "shuffle" declarations// and inline code.// microsoft dhtml behaviors add the interface first, then// apply inline script.// to achieve this, we have to strip out all of the inline// code, leaving only function declarations. the inline code// then gets appended to the script block for later// execution.// in between the function declarations and inline script, we// sandwich the property getters and setters.// this is a real nuisance actually...// on the upside regular expressions are really quick...// i'm using "#" as a placeholder, so i'll have to escape these out_script = _script.replace(/#/g, "\\x23");// parse out strings, regexps and program// blocks - anything between curly braces {..}var $ = [_declarations.join($SEPARATOR)];var $BLOCKS_REGEXPS_STRINGS = /(\"[^\"\n]+\")|(\/[^\/\n]+\/)|(\{[^\{\}]*\})/g;var _ENCODED = /#(\d+)\b/g;// store a string and return a unique idfunction _encode($match) {return "#" + $.push($match)};function _decode($match, $index) {return $[$index - 1]};while ($BLOCKS_REGEXPS_STRINGS.test(_script)) {_script = _script.replace($BLOCKS_REGEXPS_STRINGS, _encode);}// we are now left with function declarations and inline statements// remove function declarations and save themvar $FUNCTIONS = /\n\s*function[^\n]*\n/g;var _functions = _script.match($FUNCTIONS) || [];_script = _script.replace($FUNCTIONS, "");// re-assemble the encoded script, in the following// order: function declarations, interface definition// (getters and setters), inline script_script = _functions.concat("#1", _script).join($SEPARATOR);// decode the scriptvar i = $.length;do _script = _script.replace("#" + i, $[--i]); while (i);// end: annoying parse of script// build the final script_script += _defaults;// create an anonymous function in the global namespace.// this function will add the interface defined by the dhtml behavior.// after we've built this function we'll store it so that we don't// have to go through this process again.document.behaviorUrns[_url] = new Function("element", "with(this){" + _script + "}");}// because we loaded synchronously (or got it from the cache)// we can apply the behavior immediately...document.behaviorUrns[_url].call(this, this);// this might mean somthing laterreturn _cookie;} catch ($error) {return 0;}};// implement the removeBehavior method for all elementsElement.prototype.removeBehavior = function($cookie) {// mmm, not in a hurry to write this};// cache for previously loaded behaviors// -also store some "default" behaviorsdocument.behaviorUrns = {__private : []};// support multiple behaviors and ondocumentreadywindow.addEventListener("load", function() {try {var $handlers = document.behaviorUrns.__private;var i = $handlers.length;while (i) $handlers[--i]();delete document.behaviorUrns.__private;} catch ($ignore) {}}, false);}]]></constructor></implementation></binding><binding id="-moz-ie"><implementation><constructor><![CDATA[if(!this.attachEvent){// ------------------------------------------------------------------// explorer emulation for mozilla// ------------------------------------------------------------------// thanks to Erik Arvidsson (http://webfx.eae.net/dhtml/ieemu/)/* we're going to mess about with some of mozilla's interfaces tomake them more explorer-like*//* note: in my comments where i say support/mimic a propertysupport = exactly the same as explorermimic = close enough*/// CSSStyleDeclaration// -------------------// support microsoft's styleFloatCSSStyleDeclaration.prototype.__defineGetter__("styleFloat", function() {return this.cssFloat;});CSSStyleDeclaration.prototype.__defineSetter__("styleFloat", function($value) {this.cssFloat = $value;});// mimic microsoft's pixel representations of left/top/width/height// the getters only work for values that are already pixelsCSSStyleDeclaration.prototype.__defineGetter__("pixelLeft", function() {return parseInt(this.left) || 0;});CSSStyleDeclaration.prototype.__defineSetter__("pixelLeft", function($value) {this.left = $value + "px";});CSSStyleDeclaration.prototype.__defineGetter__("pixelHeight", function() {return parseInt(this.height) || 0;});CSSStyleDeclaration.prototype.__defineSetter__("pixelHeight", function($value) {this.height = $value + "px";});CSSStyleDeclaration.prototype.__defineGetter__("pixelTop", function() {return parseInt(this.top) || 0;});CSSStyleDeclaration.prototype.__defineSetter__("pixelTop", function($value) {this.top = $value + "px";});CSSStyleDeclaration.prototype.__defineGetter__("pixelWidth", function() {return parseInt(this.width) || 0;});CSSStyleDeclaration.prototype.__defineSetter__("pixelWidth", function($value) {this.width = $value + "px";});// for older versions of gecko we need to use getPropertyValue() to// access css properties returned by getComputedStyle().// we don't want this so we fix it.try {var $computedStyle = getComputedStyle(this, null);// the next line will throw an error for some versions of mozillavar $test = $computedStyle.display;} catch ($ignore) {// the previous line will throw an error for some versions of mozilla} finally {if (!$test) {// the above code didn't work so we need to fix CSSStyleDeclarationvar $UPPER = /[A-Z]/g;function _dashLower($match){return "-" + $match.toLowerCase()};function _cssName($propertyName) {return $propertyName.replace($UPPER, _dashLower)};for (var $propertyName in this.style) {if (typeof this.style[$propertyName] == "string") {CSSStyleDeclaration.prototype.__defineGetter__($propertyName, function() {return this.getPropertyValue(_cssName($propertyName));});}}}}// HTMLDocument// ------------// support microsoft's "all" propertyHTMLDocument.prototype.__defineGetter__("all", function() {return this.getElementsByTagName("*");});// mimic the "createEventObject" method for the document objectHTMLDocument.prototype.createEventObject = function() {return document.createEvent("Events");};// HTMLElement// -----------// mimic microsoft's "all" propertyHTMLElement.prototype.__defineGetter__("all", function() {return this.getElementsByTagName("*");});// support "parentElement"HTMLElement.prototype.__defineGetter__("parentElement", function() {return (this.parentNode == this.ownerDocument) ? null : this.parentNode;});// support "uniqueID"HTMLElement.prototype.__defineGetter__("uniqueID", function() {// a global counter is stored privately as a property of this getter function.// initialise the counterif (!arguments.callee.count) arguments.callee.count = 0;// create the id and increment the countervar $uniqueID = "moz_id" + arguments.callee.count++;// creating a unique id, creates a global referencewindow[$uniqueID] = this;// we don't want to increment next time, so redefine the getterthis.__defineGetter__("uniqueID", function(){return $uniqueID});return $uniqueID;});// mimic microsoft's "currentStyle"HTMLElement.prototype.__defineGetter__("currentStyle", function() {return getComputedStyle(this, null);});// mimic microsoft's "runtimeStyle"HTMLElement.prototype.__defineGetter__("runtimeStyle", function() {//# this doesn't work yet (https://bugzilla.mozilla.org/show_bug.cgi?id=45424)//# return this.ownerDocument.defaultView.getOverrideStyle(this, null);return this.style;});// support "innerText"HTMLElement.prototype.__defineGetter__("innerText", function() {return this.textContent;});HTMLElement.prototype.__defineSetter__("innerText", function($value) {this.textContent = $value;});// mimic the "attachEvent" methodHTMLElement.prototype.attachEvent = function($name, $handler) {this.addEventListener($name.slice(2), $handler, false);};// mimic the "removeEvent" methodHTMLElement.prototype.removeEvent = function($name, $handler) {this.removeEventListener($name.slice(2), $handler, false);};// mimic the "createEventObject" methodHTMLElement.prototype.createEventObject = function() {return this.ownerDocument.createEventObject();};// mimic the "fireEvent" methodHTMLElement.prototype.fireEvent = function($name, $event) {if (!$event) $event = this.ownerDocument.createEventObject();$event.initEvent($name.slice(2), false, false);this.dispatchEvent($event);// not sure that this should be here??if (typeof this[$name] == "function") this[$name]();else if (this.getAttribute($name)) eval(this.getAttribute($name));};// support the "contains" methodHTMLElement.prototype.contains = function($element) {return Boolean($element == this || ($element && this.contains($element.parentElement)));};// Event// -----// support microsoft's proprietary event propertiesEvent.prototype.__defineGetter__("srcElement", function() {return (this.target.nodeType == Node.ELEMENT_NODE) ? this.target : this.target.parentNode;});Event.prototype.__defineGetter__("fromElement",function() {return (this.type == "mouseover") ? this.relatedTarget : (this.type == "mouseout") ? this.srcElement : null;});Event.prototype.__defineGetter__("toElement", function() {return (this.type == "mouseout") ? this.relatedTarget : (this.type == "mouseover") ? this.srcElement : null;});// convert w3c button id's to microsoft'sEvent.prototype.__defineGetter__("button", function() {return (this.which == 1) ? 1 : (this.which == 2) ? 4 : 2;});// mimic "returnValue" (default is "true")Event.prototype.__defineGetter__("returnValue", function() {return true;});Event.prototype.__defineSetter__("returnValue", function($value) {if (this.cancelable && !$value) {// this can't be undone!this.preventDefault();this.__defineGetter__("returnValue", function() {return false;});}});// mozilla already supports the read-only "cancelBubble"// so we only need to define the setterEvent.prototype.__defineSetter__("cancelBubble", function($value) {// this can't be undone!if ($value) this.stopPropagation();});Event.prototype.__defineGetter__("offsetX", function() {return this.layerX;});Event.prototype.__defineGetter__("offsetY", function() {return this.layerY;});// and that's it!// thanks mozilla for being such a developer's playground :D}]]></constructor></implementation></binding><binding id="block-netscape6"><content><html:script type="text/javascript"><![CDATA[// netscape6 does not retain the -moz-binding css property value// so we disable moz-behaviorsif (/netscape6/i.test(navigator.userAgent)) {document.styleSheets[0].insertRule("*{-moz-binding:none!important}", 0);}]]></html:script><children/></content></binding><!-- manually attach behaviors to child elements of <table>s --><binding id="table"><implementation><constructor><![CDATA[var i, j;if (tHead) tHead.addBehavior(0);for (i = 0; i < tBodies.length; i++) tBodies[i].addBehavior(0);for (i = 0; i < rows.length; i++) {for (j = 0; j < rows[i].cells.length; j++) {rows[i].cells[j].addBehavior(0);}}if (tFoot) tFoot.addBehavior(0);]]></constructor></implementation></binding></bindings>