diff --git a/.gitignore b/.gitignore deleted file mode 100644 index d214bf775..000000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.DS_Store -pkg -test/unit/tmp/* -test/unit/browsers.yml -doc -tmp -*.pdoc.yaml \ No newline at end of file diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 0bce64053..000000000 --- a/.gitmodules +++ /dev/null @@ -1,20 +0,0 @@ -[submodule "vendor/caja_builder"] - path = vendor/caja_builder - url = git://github.com/tobie/unittest_js_caja_builder.git -[submodule "vendor/pdoc"] - path = vendor/pdoc - url = git://github.com/tobie/pdoc.git -[submodule "vendor/sprockets"] - path = vendor/sprockets - url = git://github.com/sstephenson/sprockets.git - - -[submodule "vendor/nwmatcher/repository"] - path = vendor/nwmatcher/repository - url = git://github.com/dperini/nwmatcher.git -[submodule "vendor/sizzle/repository"] - path = vendor/sizzle/repository - url = git://github.com/jquery/sizzle.git -[submodule "vendor/slick/repository"] - path = vendor/slick/repository - url = git://github.com/mootools/slick.git diff --git a/404.html b/404.html new file mode 100644 index 000000000..f1c60284a --- /dev/null +++ b/404.html @@ -0,0 +1,25 @@ + + + + + Prototype JavaScript Framework + + + + +
+ + +
+

404 - File not found.

+
+ + +
+ + diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index 796e90876..000000000 --- a/CHANGELOG +++ /dev/null @@ -1,1364 +0,0 @@ ------------------------------------------------------------------------------ -NOTE: This changelog is no longer updated. Consult the commit history for a -list of changes from version to version. ------------------------------------------------------------------------------ - -*1.7* (November 16, 2010) - -* Ensure `Element#update` works with string content that includes a LINK tag in Internet Explorer. [#264 state:resolved] (Tobias H. Michaelsen, Andrew Dupont) - -* Treat a 304 HTTP status as a successful response. [#331 state:resolved] (Kenneth Kin Lum, Andrew Dupont) - -* Handle sparse arrays properly in `Array#_each` to match behavior with browsers' built-in `Array#forEach` (and ES5). [#790 state:resolved] (Andriy Tyurnikov, Yaffle, Andrew Dupont) - -* Make `Event.extend` work with legacy IE events in IE 9. (Andrew Dupont) - -* Stop appending `&_=` to the parameters for non-GET Ajax requests in Safari. We no longer support any version of Safari for which this is necessary. [#327 state:resolved] (John-David Dalton, Andrew Dupont) - -* Ensure `Form.focusFirstElement` doesn't raise an exception on forms with no fields. [#341 state:resolved] (achernin, Andrew Dupont) - -* Define a `relatedTarget` property on extended mouseenter/mouseleave events in IE's legacy event system. [#708 state:resolved] (Walter Smith, Tobie Langel, Andrew Dupont) - -* Fix odd behavior with `new Element('select')` in IE6-7. [#480 state:resolved] (Bruce Harris, kangax, Andrew Dupont) - -* Extend BUTTON elements with everything defined in Form.Element.Methods. Ensure BUTTON elements are traversed in Form.getElements and serialized in Form.serialize. (Luis Gomez, Samuel Lebeau, kangax, Andrew Dupont) - -* Ensure Object.isFunction returns `false` for RegExp objects. [#661 state:resolved] (James, kangax, Andrew Dupont) - -* Revert Opera-specific behavior for calling Element#getStyle with (left|right|top|bottom). [#268 state:resolved] (kangax, Andrew Dupont) - -* Fix issue with Event#isMiddleClick and #isRightClick on Safari and Chrome. [#731 state:resolved] (Arthur Schreiber) - -* Fix issue where an Ajax request in IE sometimes returns 1223 instead of 204 as the status code. [#129 state:resolved] (adevadeh, gordyt, Andrew Dupont) - -* Add Object.isDate. [#443 state:resolved] (Nesterenko Dmitry, kangax, Samuel Lebeau, Andrew Dupont) - -* Handle cases where `document` or `document.documentElement` is passed into Element#getOffsetParent. Fixes IE errors with many layout/positioning methods. [#90 state:resolved] (Padraig Kennedy, Andrew Dupont) - -* Wrap `element` in `$` for Element#cumulativeOffset, #viewportOffset, #positionedOffset, and #getOffsetParent. [#782 state:resolved] (Radoslav Stankov, Andrew Dupont) - -*1.7_rc3* (October 11, 2010) - -* Feature detect IE's legacy event system, since IE9 now supports DOM L2 Events. (Michael Sciacqua, kangax, Andrew Dupont) - -* Fix an issue in IE9 beta where the `value` attribute of an element would not get set. (Andrew Dupont) - -* Move all offset methods to layout.js, eliminating some code repetition. - -* Remove unit test for passing a DOM node into `Object.toJSON`. To continue to support this use case would require bypassing IE's native JSON implementation. (Tobie Langel, Thomas Fuchs, Samuel Lebeau, Andrew Dupont) - -* Ensure hidden absolutely-positioned elements are sized correctly when they have no explicit width set. [#1084 state:resolved] (Viktor Kojouharov, Andrew Dupont) - -* Change custom events implementation to use the `onlosecapture` event instead of the `onfilterchange` event for non-bubbling custom events in Internet Explorer. (John-David Dalton, Andrew Dupont) - -* Revert `Element.getHeight` and `Element.getWidth` to their previous behavior in order to ensure backward-compatibility. (Sam Stephenson, Andrew Dupont) - -* Fix accidental declaration of `purgeElement` as a global function. [#1089 state:resolved] (Viktor Kojouharov, Andrew Dupont) - -* Ensure `Element.Layout` gives accurate measurements for percentages on all elements. Fix inaccurate measurements on `position: fixed` elements with percentages. [#1040 state:resolved] (Dan Popescu, Riccardo De Agostini, Andrew Dupont) - -* Fix issue with retrieving border-box-(height|width) of hidden elements. [#1035 state:resolved] (Francois-Pierre Bouchard, Andrew Dupont) - -* Ensure we clean up after ourselves for all `width` and `height` computations in `Element.Layout`. (Sam Stephenson, Andrew Dupont) - -*1.7_rc2* (May 12, 2010) - -* Remove redefinition of `Element#cumulativeOffset` when `getBoundingClientRect` is present, as it seems to give inaccurate results. (Andrew Dupont) - -* Optimize element purging. (RStankov, Andrew Dupont) - -* Add `Element.purge` for cleaning up event listeners and element storage keys on elements that will be removed from the page. Make `Element.update` perform similar cleanup automatically. (Andrew Dupont, Tobie Langel) - -* The second argument to Event.Handler callbacks is the target element when no selector is present, or the matching element when a selector is present. Callbacks are always bound to the original element. (sam) - -* Fix issue where `Element.Layout#get` would fail to interpret negative pixel values. (Sebastien Gruhier, Andrew Dupont) - -* Fix bugs in layout.js. Add tests for `Element.Layout#toCSS`, `#toObject`, and `#toHash`. (RStankov, Andrew Dupont) - -* Add `Element.Layout#toObject` and `Element.Layout.toHash`. (Andrew Dupont) - -* Make `Element.Layout#toCSS` return camelized property names, as expected by `Element.setStyle`. [#1021 state:resolved] (njakobsen, Andrew Dupont) - -*1.7_rc1* (April 1, 2010) - -* Add an `Event.Handler` class, plus `Event.on` and `Element#on` methods, for simplified event delegation. (sam, Tobie Langel, Andrew Dupont) - -* Make `Element.Layout` properly interpret computed non-integer pixel values. (e.g., Firefox can report "12.5px" as a computed style value.) (henrymazza) - -* Fix deprecated Selector.matchElements. (Tobie Langel) - -* Make Object.keys ES5 compliant. (Tobie Langel) - -* Make Prototype's JSON implementation EcmaScript 5 compliant. [#453 state:resolved] (Tobie Langel) - -* Also detect embedded (UIWebView) mobile Safari. (Thomas Fuchs) - -* Avoid object creation and an unnecessary function call in `Class#addMethods`, when working around JScript DontEnum bug. Replace with feature test and a simple boolean check at runtime. (kangax) - -* Optimize Element#immediateDescendants. (kangax, Tobie Langel) - -* Remove unnecessary function object creation and `Number#times` in `Element._getContentFromAnonymousElement`. (kangax) - -* Eliminate runtime forking and long method lookup in `Element.hasAttribute`. (kangax) - -* Remove redundant ternary. (kangax) - -* Avoid repeating declaration statements where it makes sense, for slightly better runtime performance and minification. (kangax) - -* Make `Event.stopObserving` return element in all cases. [#810 state:resolved] (Yaffle, Tobie Langel) - -* String#startsWith, String#endsWith performance optimization (Yaffle, Tobie Langel, kangax) - -* Rewrite String#camelize using String#replace with a replacement function (Phred, John-David Dalton, Samuel Lebeau, kangax) - -*1.6.1* (August 24, 2009) - -* Avoid triggering a warning when Java is disabled in IE8. [#668 state:resolved] (orv, kangax, Andrew Dupont, Tobie Langel) - -* Simplify String#(un)escapeHTML and remove their DOM dependencies. (Tobie Langel) - -* Update UnittestJS. Modifiy test template accordingly. (Tobie Langel) - -* Remove redundant if statement in Element#readAttribute. (Tobie Langel) - -* Add missing semicolons. [#751 state:resolved] (Diego Perini) - -* Remove expensive (for such low-level method) internal `getClass` in favor of plain string comparison (kangax) - -* Fix `PeriodicalExecuter` so that it no longer suppresses exceptions. [#696 state:resolved] (Samuel Lebeau, Yaffle) - -* Fix issue related to escaping of selectors for querySelectorAll. [#559 state:resolved] (Jorn Holm) - -*1.6.1_rc3* (June 16, 2009) - -* Fixed a variety of non-ASCII chars and similar [#610 state:resolved] (T.J. Crowder) - -* Add Chrome 1+ to the list of supported browsers. (kangax) - -* Fix `Template#evaluate` "eating" previous character if `null` was returned from `toTemplateReplacements` function. (Nir, Jürgen Hörmann, kangax) - -* Make sure (deficient) APPLET, OBJECT and EMBED elements are extended with simulated methods in IE8. Return early if `_extendedByPrototype` is present on an element. (Tobie Langel, kangax) - -* Replace array creation and `Array#include` with a more efficient `RegExp#test`. (kangax) - -* Reorganize the way `ElementExtensions` are defined. Make sure elements used in SpecificElementExtensions are cleaned up. (kangax) - -* Make sure $A works with primitive values. (mr_justin, kangax) - -* Do not browser sniff when forking `unmark` function in selector suite. Instead use a proper test - PROPERTIES_ATTRIBUTES_MAP. (kangax) - -* Do not use short-hand element methods notation (@element.getStyle() -> Element.getStyle(@element)) for performance reasons. Do not use `$A` and `Array.prototype.shift` when `Array.prototype.slice` can be used instead. (kangax) - -* `Prototype.Browser.Opera` now uses stronger inference and is determined by [[Class]] of `window.opera` being - "Opera". (kangax) - -* Fix error in event.js which prevented attaching more than one responder for an event name/element combination. [#651 state:resolved] (Rob Lineweaver) - -* Do not sniff when testing for IE's proprietary mouseenter/mouseleave events support. Use more robust inference instead. (kangax) - -* Use `Prototype.emptyFunction` consistently throughout unit tests. [#253 state:resolved] (Michael M Slusarz, John David Dalton, kangax) - -* deprecation extension: mark Array#reduce() as removed. [#569 state:resolved] (Tobie Langel) - -* `Form.serialize` now works safely with forms that have "length"-named elements. [#77 state:resolved] (Peter Adrianov, John-David Dalton, kangax) - -*1.6.1_rc1* (March 22, 2009) - -* `Element#update` now takes care of SCRIPT elements in IE. [#573 state:resolved] (Martin, Tobie Langel, kangax) - -* Remove unused local variables from `Element.extend`. Fix one of the form tests to remove `_extendedByPrototype` by setting it to `undefined` rather than `false` (`_extendedByPrototype` being `false` does not force `Element.extend` to re-extend element). (T.J. Crowder, kangax) - -* Make test for `escapeHTML`/`unescapeHTML` more strict. (Chrome 1.x escapes "<" and "&" with `innerHTML`, but not ">") (kangax) - -* Remove another sniffing from one of DOM tests. Fixes last IE8 failure. (kangax) - -* `Element.extend` now takes care of IE8 bug when HTMLAppletElement and HTMLObjectElement objects do not inherit from `Element.prototype`. (kangax) - -* Fix DOM tests to use proper feature test when testing `setOpacity` (kangax) - -* Fix another failure in IE8, `for`/`htmlFor` {get/set}Attribute translation. (kangax) - -* Fix `Element#writeAttribute` and `Element#readAttribute` failures in IE8 due to lack of proper feature testing. (kangax) - -* Remove sniffing from one of the DOM tests, which produced failures in IE8. (kangax) - -* Fix `Form.reset` test where `respondsTo` wouldn't detect a method due to typeof returning "object" (rather than "function") in IE (kangax) - -* Remove Array#reduce which currently overrides native `reduce` in clients implementing JS1.8, e.g. Firefox 3+ (Tobie Langel, Andrew Dupont, kangax) - -* Make sure try/catch/finally is used instead of try/finally for clients without support for the latter one (e.g. Blackberry, IE) (Ville Koskinen, kangax) - -* Use `in` operator when accessing property of a nodelist to prevent Safari <=2.0.4 from crashing (kangax) - -* Add Element#clone as a safe wrapper of native `cloneNode`. (Andrew Dupont, kangax) - -* Add tests to ensure IE8 properly assigns a class name in the `Element` constructor. [#529 state:resolved] (Riki Fridrich, Andrew Dupont) - -* Remove sniffing from `Element` when detecting broken `setAttribute` in IE. [#571 state:resolved] (kangax) - -* Remove sniffing from `Element.update` branching in favor of feature detection. [#574 state:resolved] (kangax) - -* Remove sniffing when branching `escapeHTML` and `unescapeHTML`. [#570 state:resolved] (kangax) - -* Redefine Element#down in IE 6-7 to avoid extending all descendants when no selector is given. [#452 state:resolved] (eno, Andrew Dupont) - -* Reverse the definitions of Event#pointer(X|Y) and Event#pointer to prevent unnecessary computation. [#403 state:resolved] (Nick Stakenburg, Andrew Dupont) - -* Add first-class support for `mouseenter` and `mouseleave` events in non-IE browsers (IE supports them natively). [#350 state:resolved] (Nick Stakenburg, Andrew Dupont) - -* Make sure `_extendedByPrototype`, `_countedByPrototype`, and `prototypeUID` node expandos are accessed with `typeof` to prevent errors in some environments. [#354 state:resolved] (Hilberty, kangax, Andrew Dupont) - -* Fix issue where Opera 9.x returns incorrect results on certain Selector queries with descendant combinators. [#395 state:resolved] (Arpan, fearphage, kangax, Andrew Dupont) - -* Null out references to elements in cache on page unload. Need this in addition to the Event#stopObserving calls to clean up memory leaks. [#425 state:resolved] (ykphuah, mr_justin, Andrew Dupont) - -* Ensure `toString` and `valueOf` properties are copied to a subclass only when necessary in IE6. [#382 state:resolved] (Samuel Lebeau) - -* Make sure `getAttribute` is used without flag when accessing the "type" attribute of an iframe (IE throws error otherwise). [#118 state:resolved] (Zekid, kangax) - -* String#gsub should escape RegExp metacharacters when the first argument is a string. [#469 state:resolved] (michael, kangax) - -* Fix order of replacement in String#unescapeHTML [#544 state:resolved] (SWeini, kangax) - -* Fix issue where a Selector query rooted on a node that had not been attached to the document failed in IE. [#464 state:resolved] (jddalton, kangax, Douglas Fraser, Andrew Dupont) - -* Fix Selector to match elements with attributes containing hyphens. [#285 state:resolved] (leiyou, jddalton, kangax) - -* Make sure Form.reset always returns a reference to the receiver element. [#309 state:resolved] (Phil, kangax) - -* Escape ":" and "." characters when doing contextual CSS selection in browsers that support querySelectorAll. [#559 state:resolved] (fxtentacle, Andrew Dupont) - -* Ensure the `target` property on events is never undefined in IE. [#383 state:resolved] (Mathias Karstädt, Diego Perini, Andrew Dupont) - -* Ensure Element#descendants always returns an array. [#373 state:resolved] (kangax) - -* Don't switch fixed position elements to absolute in Element.getDimensions [#543 state:resolved] (James Wheare) - -* Avoid infinite loops when calling String#sub with empty pattern [#534 state:resolved] (Samuel Lebeau) - -* Switch to Sprockets for building the Prototype distfiles. (sam) - -* Switch Object.is(Array|String|Number) to use the vastly-superior approach discovered by Juriy. (kangax) - -* Further fix to ensure Object.is(String|Number) do not throw exceptions on host objects in IE. (grepmaster, kangax, Tobie Langel, Andrew Dupont) - -* Ensure Enumerable#grep can handle strings with RegExp metacharacters. (Marton Kiss-Albert, kangax) - -* Switch to the "doScroll approach" for the dom:loaded custom event. (javier, Diego Perini, Nick Stakenburg, Andrew Dupont) - -* Optimize document.viewport.get(Dimensions|Width|Height). (Nick Stakenburg, Andrew Dupont) - -* Fix issue where Object#isString and Object#isNumber return false for String and Number "wrapper" objects. (atrepp, Samuel Lebeau, Andrew Dupont) - -* Set document.loaded = true before firing dom:loaded custom event. (Andrew Dupont) - -* Allow Element#store to accept an object containing several key/value pairs. (ZenCocoon, Andrew Dupont) - -* Change Element#store to return the element itself (for chaining). (Andrew Dupont) - -* Add non-bubbling custom events. A new final argument to Element#fire defaults to `true`; pass `false` to prevent bubbling when firing a custom event. (Andrew Dupont) - -* Alter event system to use new element storage API rather than have its own global hashtable. (Andrew Dupont) - -* Add Element#store and Element#retrieve for safe, hash-backed storage of element metadata (no memory leaks). Also add Element#getStorage for working with the element's storage hash directly. Hat tip: Mootools. (ZenCocoon, Andrew Dupont) - -* Fix issue where certain versions of Safari treat class names case-insensitively in Selector/$$ queries. (Andrew Dupont, kangax, Brice) - -* Fix issue where Function#argumentNames returned incorrect results in IE when comments were intermixed with argument names. (Christophe Porteneuve, T.J. Crowder) - -* Selector.patterns should be represented as an ordered structure. (ADO, kangax) - -* Performance improvements in Function methods (Samuel Lebeau, kangax, jddalton, Tobie Langel). - -*1.6.0.3* (September 29, 2008) - -* Add support for the Chrome browser in jstest.rb. (Andrew Dupont) - -* Workaround a JavaScript exception in Opera. (Thomas Fuchs) - -* Improve NodeList detection for Safari's $A function. (Garrett Smith, jddalton) - -* Use different tactic to sniff for Opera in order to avoid false positives in IE. (Tobie Langel, jddalton) - -* Rename variable in Form.Element.Serializers.select. (jddalton) - -* Coerce Opera's version string into a number whenever we need to sniff. (Sam Holman, jddalton) - -* Ensure Object.isElement handles "falsy" values properly. (kangax) - -* Fix exiting test task on INT signal. (Samuel Lebeau) - -* Fix unit test freeze in IE. (Tobie Langel) - -* Ensure Hash does not return keys from the prototype chain (e.g., constructor, valueOf, toString). (kangax) - -* Fix toString/valueOf sharing same method reference via closure in Class#addMethods. Use plain property assignment, since Object.extend fails to enumerate over toString/valueOf. (kangax) - -* Stop Form.Element.disable from stealing focus. (jddalton) - -* Ensure Element.hide and Element.show return an element, even if you pass an element ID. (Andrew Dupont) - -* Fix an issue where Element#getStyle('height') returns null if the height is set to "auto." (kangax, jddalton) - -* Add unit tests for Element#descendantOf. (jddalton) - -* Form#serializeElements should not serialize file inputs. (kangax, Lonesome Boy) - -* Fix an issue with calling Event.pointer before the DOM is loaded. (kangax, jddalton) [#4 state:resolved] - -* Element#down on an input element should not raise error. (humeniuc, kangax) - -* More unit tests for Object.isHash. (Tobie Langel) - -* Allow Function#argumentNames to handle line breaks between arguments. (Geoff M. Granum, Tobie Langel) [#63 state:resolved] - -* For consistency, add additional optional parameter "context" to Number.prototype.times. (Samuel Lebeau) - -* Replace all instances of foo.__proto__ by foo['__proto__'] for Caja-compliance. (Tobie Langel) - -* Speed up Function#argumentNames. Avoid Enum dependency. (Samuel Lebeau, Tobie Langel) - -* Fix Event#element accessing inexistent tagName property (e.g. when element is a document). (kangax) - -* Amended failing Element#identify test. - -* Refactor unit tests. Unit tests are now dynamically generated from a JavaScript test file and optional HTML, JS and CSS fixtures. [Tobie Langel] - -* Fix issue where Safari improperly reports an element as a descendant of itself. - -* Greatly simplify IE's implementation of Element#descendantOf. - -* Prevent exception when using Selector to search for an attribute that is not present. [gryn, Andrew Dupont] - -* Fix issues where Firefox improperly returns the wrong node from a call to Event.element. Also fixes possible exception in Event.element in IE. [jdalton, Andrew Dupont] - -* Fix issue where Safari 3 deletes custom properties from the document object when the page is returned to via the back button. [mzsanford, kangax, Andrew Dupont] - -* Integrate support for the W3C Selectors API into the Selector class. Will now use the API when possible (browser supports the API *and* recognizes the given selector). Means minor changes to the semantics of :enabled, :disabled, and :empty in order to comply with CSS spec. - -* Avoid re-extending element in Element#getDimensions. [kangax] - -* Prevent Hash#toQueryString from serializing objets. [kangax, Tobie Langel] - -* Fix Event#pointer in IE standard mode. Closes #9920. [kangax, Tobie Langel] - -* Instanciate Test.Unit.Logger on window load. [Tobie Langel] - -* Unit tests clean-up. [Tobie Langel] - -* Refactor String#escapeHTML to avoid using the `with` statement. [Tobie Langel] - -* Remove usage of the `with` statement from unit tests. [Tobie Langel] - -* Complete rewrite of the deprecation helper, now renamed UpdateHelper and useable by third-party libs. [Tobie Langel] - -* Make Element#writeAttribute handle frameborder attribute in IE. Closes #11068. [staaky, Tobie Langel] - -* Minor clean-up of selector.js. Closes #10844. [RQuadling] - -* Make String#unescapeHTML strip tags in IE. Closes #10173. [kangax] - -* Stop form observers in unit tests. Closes #10938. [kangax] - -* Performance improvements for Enumerables. Closes #11264. [Ben, Samuel Lebeau] - -* deprecation extension: mark Hash.toJSON() as removed. [Tobie Langel] - -* deprecation extension: mark Class.create() used without arguments as deprecated. [Tobie Langel] - -* deprecation extension: mark Event.unloadCache as removed rather than deprecated. [Tobie Langel] - -* deprecation extension: log everything *but* deprecations with console.error. [Tobie Langel] - -* Change deprecation extension to use Firebug's console.warn and console.error. [Andrew Dupont, Tobie Langel] - -* Make tagName comparisons XHTML-compliant. Closes #11012, #11013, #11014. [cfis, Tobie Langel] - -* Avoid breaking Element.prototype in browsers which support it. Closes #11004. [cfis, Tobie Langel] - -* Prevent Element#cumulativeOffset, Element#getOffsetParent, Element#positionedOffset, Element#viewportOffset and Element#clonePosition from throwing an error in IE when called on a parent-less element. Closes #9416, #10192, #10248. [ronstoney, psiborg, kangax] - -* Prevent Enumerable#eachSlice from entering into an endless loop if passed an argument smaller than 1. Closes #10665. [kangax, Tobie Langel] - -* Allow Selector to correctly detect the presence of namespaced attributes. Closes #10987. [Samuel Lebeau, Tobie Langel] - -* Make Element#absolutize and Element#relativize always return element. Closes #10983. [kangax] - -* Add deprecation extension. [Tobie Langel] - -*1.6.0.2* (January 25, 2008) - -* Update the list of officially supported browsers in the README. [sam] - -* Add tests for Element#descendantOf that deal with dynamically-created elements. [Andrew Dupont] - -* Ensure positionedOffset properly considers "position: fixed" elements. Also ensures IE reports offsets correctly by triggering hasLayout when a "static" element has a "fixed" element as an offset parent. Closes #10644. [heygrady, kangax, Andrew Dupont] - -* Roll back the fix for #9609, since it does not work in Opera. Instead, avoid using "valueOf" or "toString" as field names in forms. - -* Prevent DOM node expandos _countedByPrototype and _prototypeEventID from being serialized into (inner|outer)HTML in IE. Closes #10909. [dcpedit, Tobie Langel, Andrew Dupont] - -* Make Ajax.Request#isSameOrigin JavaScript Lint compliant. [Andrew Dupont] - -* Properly serialize form fields with names that collide with built-in JS properties (like "length" or "toString"). Closes #9609. [gryn, kangax] - -* Make Object.isArray correctly identify arrays created in another frame. Closes #10374. [pointy, Dean Edwards, Andrew Dupont, Tobie Langel] - -* Fixed issue where Element#match failed on attribute selectors with single or double quotes. Closes #10067. [Cezary Okupski, Andrew Dupont] - -* Add tests for Element#match. [Tobie Langel] - -* Fix Element#writeAttribute to work with 'cellspacing' and 'cellpadding' attributes in IE. Closes #9983. [/dev/urandom, Tobie Langel] - -* Prevent a potential security issue for cross-site ajax requests. [Alexey Feldgendler, sam, Tobie Langel] - -* Test for attribute existence before applying more complex CSS3 selectors. Closes #10870. [arty, Tobie Langel] - -* Fix "function $A" declaration inside of a conditional (confuses IE). Closes #10882. [Jacco, Andrew Dupont] - -* Fixed selector parsing so that "#foo [bar=baz]" is treated the same way as "#foo *[bar=baz]". Closes #10734. [jlukas, kangax, Andrew Dupont] - -* Fix Element#descendantOf logic in IE. Closes #10413. [martymix, kamil.szot] - -* Fix missing "var" in Element#insert. Closes #10838. [Lantash] - -* Add Test.Unit.MessageTemplate class. Add flunk, buildMessage and assertBlock methods to Test.Unit.Assertions. Refactor accordingly. [Tobie Langel] - -* Remove useless binding in Template#evaluate. [Tobie Langel] - -* Make Object.inspect more robust. [Tobie Langel] - -* Add a description to :test and :dist rake tasks. [Christoph Sturm] - -* Fix Selector.matchElements to allow for coma-separated selectors in Element#up/next/previous and Event#findElement. [Samuel Lebeau, Tobie Langel] - -* Test.Unit refactoring. Allow running multiple instances of Test.Unit.Runner on the same page. Allow rake to run specific testcases (e.g.: rake test BROWSERS=firefox TESTS=array TESTCASES=testUniq,test$w). Closes #10704, #10705, #10706. [nicwilliams, Tobie Langel] - -* Optimize property detection of outerHTML. Avoids triggering FOUC in Safari 3.0.4. Closes #10702. [subimage, Tobie Langel] - -* Add document.loaded, a boolean that is set to true once dom:loaded is fired. Setting document.loaded to true before the document is loaded prevents dom:loaded from being fired. [Tobie Langel] - -* Make Element#insert standard-compliant. Fixes an issue in FF3b2 when inserting HTML or text inside DOM nodes which aren't (yet) appended to the document. [Tobie Langel] - -* Add some missing semicolons to the source tree. Closes #10659. [Richard Quadling] - -* Ensure Ajax.Response#getHeader returns null for missing headers in Opera. [Tobie Langel] - -* Allow WEBrick to simulate slow or dropped connections and to ease Ajax request inspection. [Tobie Langel] - -* Ensure Ajax.Response#getHeader returns null for missing headers. [Tobie Langel] - -* Ensure $A creates an empty array when its argument's length is undefined. Closes #10574. [henryju, Tobie Langel] - -* Fix incorrect variable declaration in Event.fire. Closes #10329. [rubley] - -* Fix the way Selector handles [pseudoclass + combinator] with no space in between. Closes #9696. [kangax, fearphage, Andrew Dupont] - -* Optimize Element#up/down/next/previous. Closes #10353. [Dylan Bruzenak, Nick Stakenburg, Andrew Dupont] - -* Handle case-sensitivity in Selector tag names better. Closes #5052. [mexx, Andrew Dupont] - -*1.6.0.1* (December 4, 2007) - -* Change document.viewport.getDimensions to exclude scrollbars in all cases. Closes #10148, #9288. [Nick Stakenburg] - -* Add logic to Element#getStyle in Opera that fixes inaccurate reporting of computed 'width' and 'height' properties. [Andrew Dupont] - -* Ensure that an Ajax.Request's parameters option can be a Hash. Closes #10172. [kangax, sam] - -* Ensure no comment nodes are returned in Selector queries (IE improperly returns comment nodes on getElementsByTagName("*")). Change Element#descendants to use Element#getElementsBySelector in order to avoid this issue. Closes #10220. [Jeff Gobel, Andrew Dupont] - -* Re-enable the XPath approach in Selector for Safari 3. Falls back to the non-XPath version when it sees a problematic token. [Andrew Dupont] - -* Fix a bug in the IE-specific Element#descendantOf logic. [Nicholas, Andrew Dupont] - -* Make Ajax.Updater clone its options hash before modifying it. Prevents memory leaks in Ajax.PeriodicalUpdater. Closes #10049 [Mislav Marohnić, Tobie Langel]. - -* Remove useless variable in Selector.handlers.child. Closes #10006 [kuriyama] - -* Don't redeclare previously declared variables. Closes #10007 [kuriyama] - -* For consistency: use Object.isUndefined where possible. [Tobie Langel] - -* Make String#isJSON return false for empty or blank strings. Make Ajax.Response#responseJSON null when Ajax.Response#responseText is empty or blank. [Andrew Dupont, Thomas Fuchs, Tobie Langel] - -* Make Ajax.Response#_getResponseJSON use Ajax.Response#responseText. [Tobie Langel] - -* Remove the forked declaration of Hash#_each. As we are now systematically cloning the object upon instantiation, preventing iteration of shadowed properties is no longer required. [Tobie Langel] - -* Performance optimizations for Event#findElement. Make Event#findElement's expression argument optional, in which case the extended target element is returned (same as Event#element). [Tobie Langel] - -* Ensure Event#fire always returns an extended event. [Tobie Langel] - -*1.6.0* (November 6, 2007) - -* Fix Class#addMethods for "toString" and "valueOf" methods in Internet Explorer. Closes #9901. [sam] - -* Exclude Opera from using the sourceIndex approach in Element#descendantOf. [Tobie Langel, Andrew Dupont] - -* Ensure Element#hasClassName always returns a boolean. Closes #10075. [ronnylovtangen, Tobie Langel] - -* Ensure selectors of the form "[href]" (attribute token with no preceding tag name) work properly. Closes #8870. [chao, kangax, Andrew Dupont] - -* Performance optimizations for Element#descendantOf. Costliness should no longer be dependent on the difference in depth between the parent and the child. [Andrew Dupont] - -* Apply the workaround for the Firefox "blinking element" opacity=1 bug only to Firefox 1.5. [Thomas Fuchs] - -* Add event.stopped, a boolean that is set to `true` when Event#stop is called. [Andrew Dupont, sam] - -* Reset the browser's dimensions to their original settings after running the DOM viewport tests. [sam] - -* Fix the test runner for Firefox in Leopard. [sam] - -* Use String#include wherever possible. - -* In IE, allow opacity to be set on elements not yet attached to the document. Closes #9904. [Thomas Fuchs, dcpedit, Tobie Langel] - -* Avoid the try..catch block in Ajax.Response#_getResponseJSON unless required. [Tobie Langel] - -* Add more tests to Element.update. Closes #9327. [Tobie Langel] - -* Make the Ajax.Response#headerJSON property correctly decode unicode characters. Closes #9285. [Marius Feraru, Tobie Langel] - -* Make sure Event and Event.extend are defined before wrapping events and calling their handler. Prevents a known Firefox bug from throwing errors on page load/unload (cf.: https://bugzilla.mozilla.org/show_bug.cgi?id=361271). Closes #5393, #9421. [staaky, John Resig, sam, Tobie Langel] - -* Minor cosmetic changes to the display of unit tests in terminal. [Tobie Langel] - -* Make submitting forms work in Opera < 9.1. Closes #9917, #9463, #8260. [kangax] - -* Fix template evaluation with empty replacements. Closes #9692. [Ryan McGeary] - -* Hash#toTemplateReplacements is an alias for Hash#toObject so you can once again pass hashes to Template#evaluate and String#interpolate. [sam] - -* Fix Event#is(Left|Middle|Right)Click in IE. Closes #7520 (again). [Mislav Marohnić] - -*1.6.0_rc1* (October 16, 2007) - -* Ensure Event.* generic methods work in IE, even when the event is not extended. [Viktor Kojouharov, Andrew Dupont] - -* Don't translate "keypress" events into "keydown" events. [sam] - Note: "keypress" is broken in Safari <= 2.x, but Event#stop has no effect on "keydown" events. - -* Changed Element#makeClipping to remember the original overflow value, even if it's a non-inline style. [Andrew Dupont] - -* Cross-browser Event#isLeftClick with the addition of is(Middle|Right)Click. Closes #7520. [Christophe Porteneuve, Richard Quadling, Mislav Marohnić] - -* Changed Selector to use the non-XPath approach for Safari 3 because of bugs in its version of document.evaluate. [Andrew Dupont] - -* Changed the Selector regex that tests whether the selector can be expressed in XPath; added :checked, since XPath can't detect all scenarios in which an is checked. Fixes #9776. [StelardActek, kangax, Andrew Dupont] - -* Changed Selector pattern match so that descendant combinators after pseudoclass tokens are properly handled. Fixes #9696. [wiktor, kangax, Andrew Dupont] - -* Make sure $w always returns an array. [Andrew Dupont, Tobie Langel] - -* Add more tests to Hash. [Mislav Marohnić] - -* Performance enhancements to $A. Closes #9464. [Samuel Lebeau] - -* Make Function#argumentNames work with named functions. Closes #9826. [Samuel Lebeau] - -* Add Object.isHash. [Tobie Langel] - -* Performance improvements to String#times. [Martin Ström] - -* Make Ajax.Response#getHeaderJSON and Ajax.Response#getResponseJSON pseudo private instance methods. [Tobie Langel] - -* Make ObjectRange use the new Class.create syntax. [Mislav Marohnić] - -* Fix a failing ClassCreate test case in IE. [Tobie Langel] - -* Complete rewrite of the Hash class. - - !! BACKWARDS COMPATIBILITY CHANGE !! This new version of Hash is NOT backwards compatible with the former Hash class. - - Properties are now hidden away in an private store to prevent the risk of collision with Hash's instance and mixed-in methods. - This implies that properties of the hash can no longer be set, accessed or deleted directly: use the new Hash#get(key), Hash#set(key, value) and Hash#unset(key) instance methods instead. - - - Make $H(object) equivalent to new Hash(object). Both now return a new (cloned) instance of Hash in all circumstances. - - Make Hash#merge non-destructive. - - - Add Hash#update (a destructive version of Hash#merge). - - Add Hash#clone (returns a new, cloned instance of Hash). - - Add Hash#toObject (returns a clone of the contained object). - - Add Hash#get(key) (returns the value of the specified property). - - Add Hash#set(key, value) (sets the value of the given property. returns the value). - - Add Hash#unset(key) (deletes the specified property and returns its value). - - Add Hash.from as a alias to $H for consistency with Array.from. - - Add Object.toQueryString. - - - Deprecate Hash.toQueryString (use Object.toQueryString or the instance method Hash#toQueryString instead). - - - Remove Hash#remove (use Hash#unset instead). - - Remove Hash.toJSON (use Object.toJSON or the instance method Hash#toJSON instead). [sam, Tobie Langel] - -* Element#wrap now returns the wrapper instead of the element being wrapped. [sam] - -* Namespace all custom event names to avoid conflicts with native DOM events. [sam] - - All custom event names MUST include a namespace. Prefix custom event names for observe, stopObserving, and fire with the namespace followed by a colon. E.g. document.fire("widget:activated") - - The "contentloaded" event is now "dom:loaded". - - The Event.DOMEvents array is no longer present. If an event name does not include a namespace, the event is treated as a native event. - -* Clean up the new class API. [sam, Tobie Langel] - - Add Class#addMethods for adding instance methods to classes. - - Remove Class.extend and Class.mixin. - - Class.create now takes a variable number of arguments: if the first argument is a class, the newly created class inherits from that class; all other arguments are treated as successive calls to addMethods. - -* Fix contentloaded event initialization in IE. Closes #9457, #9488, #9707. [Mislav Marohnić] - -* Deprecate document.getElementsByClassName and Element#getElementsByClassName since native versions return a NodeList and we can only return an Array. Please use $$ or Element#select instead. [sam] - For more information see https://bugzilla.mozilla.org/show_bug.cgi?id=390411 - -* Fix missing "var" in selector.js. Closes #9761. [Tobie Langel] - -* Date#toJSON now returns times in UTC for better compatibility with json.js. Closes #9332. [Tobie Langel] - -* Ensure document._getElementsByXPath extends the elements it returns; fixes $$ not returning extended elements in Opera 9.2. Closes #8843. [jdalton] - -* Update Prototype.Browser.MobileSafari for iPod touch compatibility. [sam] - -* Add tests for Object.extend and Object.clone. [Tobie Langel] - -* Add a test for Form.Observer. [Christoph Sturm] - -* Make sure setting opacity works on elements that have "no layout" in IE. [Thomas Fuchs] - -* Simplify Class.create by establishing a prototype chain when subclassing. Closes #9342. [Ben Newman] - -* Fix Ajax.PeriodicalUpdater for compatibility with Ajax.Response. Closes #9321. [kampers] - -* Ensure that classes always have an initialize method. [Mislav Marohnić] - -* Update Template, Selector, Ajax.*, and ObjectRange classes to use the new class system. [Mislav Marohnić] - -* Change Abstract.TimedObserver to subclass PeriodicalExecuter and tweak its subclasses to use new inheritance functionality. TimedObserver can now be stopped the same way as PeriodicalExecuter. Closes #8589. [Mislav Marohnić] - -* Fix Class.mixin to extend the class's prototype. [Mislav Marohnić] - -* Fix superclass method call breakage from [7337]. [Mislav Marohnić, sam] - -* Change Class.extend to allow for superclass method resolution and remove Class.inherit. Closes #9274. [Samuel Lebeau] - -* Event handlers are now bound to the observed element, not the event's target element. [Dan Webb] - -* Define Node constants conditionally after checking for Node.ELEMENT_NODE presence. Add unit test to check the values of all constants. Closes #7625. [Mislav Marohnić] - -* Make sure Enumerable#include doesn't do type comparision. [Mislav Marohnić] - -* Add contextmenu to Event.DOMEvents. [Thomas Fuchs] - -*1.6.0_rc0* (August 15, 2007) - -* Fix readAttribute-related failure in form.html in IE. [sam, Andrew Dupont] - -* Fix failing dom.html and selector.html tests in IE. [Tobie Langel, Andrew Dupont] - -* Make sure the WebKit redefinition of Element#cumulativeOffset uses Element._returnOffset. Closes #9245. [mdaines] - -* Make sure Element#observe and Element#stopObserving are always chainable. [sam] - -* Event.fire/Element#fire now returns the newly-fired event instead of the event's target element. [sam] - -* Restrict Event.DOMEvents to include only events that can be supported in all browsers. [sam] - -* Fix a failing test in base.html in Safari 2. [Tobie Langel] - -* Fix Element#positionedOffset and Element#getOffsetParent for static elements on IE. [Thomas Fuchs] - -* Make sure event handlers and their wrappers are removed from the cache by Event.stopObserving. [sam, Severin Heiniger] - -* Add line numbers to failures when unit testing in Firefox. Closes #9231. [John Resig] - -* Fix Function#argumentNames for Opera and IE. [Thomas Fuchs] - -* Add Object.isString, Object.isNumber, and Object.isUndefined, and clean up the source to make use of Object.isXXX where possible. [sam] - -* Add the document.viewport object for querying dimensions and scroll offsets of the browser viewport. [Andrew Dupont, Thomas Fuchs, sam] - Example: - document.viewport.getDimensions() // { width: 1149, height: 923 } - document.viewport.getWidth() // 1149 - document.viewport.getHeight() // 923 - document.viewport.getScrollOffsets() // { left: 0, top: 1592 } - -* Add support for brackets in quoted attribute value selectors. Closes #9157. [Ken Snyder] - -* Add some missing semicolons to the source tree. Closes #9140. [jdalton] - -* Fix event extensions and custom events firing for Safari 2.0. [Thomas Fuchs] - -* Add RegExp.escape for escaping regular expression strings. Closes #9094. [Ken Snyder] - -* Make the eventName and handler arguments to Event.stopObserving optional. If no handler is specified, all handlers for the given event are unregistered. If no event name is specified, all observed events on the element are unregistered. [sam] - -* Add cross-support for the DOMContentLoaded event through a Prototype custom event on document called "contentloaded". The DOMContentLoaded event fires before window.load, when the entire HTML document, but not necessarily its images, stylesheets or other assets, has loaded. Based on [6596]. [sam, Mislav Marohnić] - Example: - document.observe("contentloaded", function() { - $$("a").invoke("identify"); // give all tags an ID - }); - -* Add Event.fire and Element.Methods.fire for firing custom events. Prototype custom events piggyback on a real DOM event ("ondataavailable"), so they bubble and cancel. You can fire custom events from any element, or fire global events on the document object. Observe custom events just as you'd observe a regular DOM event. [sam, Seth Dillingham] - -* Extend the event object with methods from Event.Methods and normalize it in IE. [sam, Mislav Marohnić] - -* Remove support for observing the capturing phase of DOM events, since we can't support it in all browsers. [sam] - -* Add Ajax.Response object which supports the following methods: responseJSON, headerJSON, getHeader, getAllHeaders and handles browser discrepancies in the other response methods. Add sanitizeJSON, evalJS and evalJSON to Ajax.Request. Closes #8122, #8006, #7295. [Tobie Langel] - -* Add an isRunningFromRake property to unit tests. [Tobie Langel] - -* Add support for Opera browser in jstest.rb. [Tobie Langel] - -* Inheritance branch merged to trunk; robust inheritance support for Class.create. Closes #5459. [Dean Edwards, Alex Arnell, Andrew Dupont, Mislav Mahronic] - - To access a method's superclass method, add "$super" as the first argument. (The naming is significant.) Works like Function#wrap. - - Class.create now takes two optional arguments. The first is an existing class to subclass; the second is an object literal defining the instance properties/methods. Either can be omitted. Backwards-compatible with old Class.create. - - Added Class.extend for dynamically adding methods to existing classes (while preserving inheritance chain). Can also be used for mixins. - - The 'constructor' property of a class instance always points back to the proper class. Class objects themselves have two special properties: 'superclass' and 'subclasses' (which default to 'null' and '[]', respectively). Allows for powerful introspection. - - Added Object.isFunction [sam] - -* Add Function#argumentNames, which returns an ordered array of the function's named arguments. [sam] - -* Prevent a crash in Safari 1.3 on String#stripScripts and String#extractScripts. Closes #8332. [grant, Tobie Langel] - -* Add Prototype.Browser.MobileSafari which evaluates to true on the iPhone's browser. [sam] - -* Optimize Selector#match and Element#match for simple selectors. Closes #9082. [Andrew Dupont] - -* Remove the dependency on Element.ClassNames from Element#addClassName/removeClassName/toggleClassName, and deprecate Element.ClassNames. Closes #9073. [Tobie Langel] - -* Make Element#wrap accept a second argument for setting attributes on the wrapper. Allow wrapping elements which are not part of the document. Closes #9071. [Tobie Langel] - -* Improvements for Element#replace, Element#update and Element#insert. Closes #7429, #9060. [Tobie Langel] - - Element#replace/update/insert uses the argument's toElement or toHTML method if present (toElement has precedence if both are present). - - Element#replace and Element#update now also accept DOM elements. - - Element#replace better handles table-related elements in IE and Opera. - -* Add Object.isArray and Object.isElement (returns true if the object is a DOM node of type 1). [Tobie Langel] - -* Add Object.toHTML (uses the object's toHTML method if present or else passes the object to String.interpret). [Tobie Langel] - -* Make Element#setStyle accept a string argument of CSS rules. Deprecate uncamelized style property names when setting styles using an object (for performance reasons). Closes #9059. [Tobie Langel] - Examples: - $('id').setStyle('font-size: 12px; float: left; opacity: 0.5'); - $('id').setStyle({fontSize: '12px', cssFloat: 'left', opacity: 0.5}); - - !! BACKWARDS COMPATIBILITY CHANGE !! - - If you have code that looks like this: - $('id').setStyle({'font-size': '12px'}); - You need to replace it with either of the following: - $('id').setStyle({fontSize: '12px'}); - $('id').setStyle('font-size: 12px;'); - -* Add Element#identify, which returns the element's ID if it exists, or sets and returns a unique, auto-generated ID (of the form "anonymous_element_" + auto-incremented digit) otherwise. Use this when you need to ensure an element has an ID. Closes #9012. [Jeff Watkins, sam, Tobie Langel] - -* Make Element#readAttribute work for cloned elements in IE. Closes #8481. [chem, Tobie Langel] - -* Template enhancements. Closes #8166. [Christophe Porteneuve] - - Added String#interpolate as a shortcut for new Template(...).evaluate(...). - - If you pass String#interpolate or Template#evaluate an object with a toTemplateReplacements() method, the return value of that method will be used as the replacement object. - - You can now substitute properties of template replacement values in template strings, using dot or bracket notation (or both). Example: - "#{name.last}, #{name.first[0]}. (#{location})".interpolate({ - name: { first: "Christophe", last: "Porteneuve" }, location: "Paris" - }) // "Porteneuve, C. (Paris)" - -* Extended grep semantics. The first argument to Enumerable#grep is now a "filter" (an object with a match() method) so you can now e.g. filter an array of DOM nodes by CSS selector. RegExp#match is now an alias to RegExp#test, so grep can still be used to filter an array of strings with a regular expression. Closes #7596. [Christophe Porteneuve, sam] - -* Make String#scan explicitly return a string. This prevents possible issues with methods expecting input data that is typeof == 'string'. Closes #6350. [AndrewRev, Tobie Langel] - -* Add Array#intersect for set intersection. Returns a new array containing all items common to the array and the argument, with duplicates removed (clone of the Ruby & method). [Thomas Fuchs] - Example: - [1,1,3,5].intersect([1,2,3]) -> [1,3] - -* Rename Element#getElementsBySelector to Element#select and add alias for Element#getElementsBySelector. [Thomas Fuchs] - -* Add Element#adjacent as a shortcut to selecting all adjacent nodes (and their children) that match a CSS selector. [Thomas Fuchs] - -* Enhance the Enumerable and Array APIs to more closely match those of JavaScript 1.6 as implemented in Firefox 1.5. Closes #6650, #8409. [Mislav Marohnić, Sylvain Zimmer] - - Add Array#lastIndexOf, and change Array#indexOf not to overwrite the native method. - - Make Enumerable use Array.prototype.forEach instead of _each when possible (slight speed increase). - - Add "filter", "entries", "every", and "some" Array aliases. - - All Enumerable methods now have an additional parameter, "context", which, if present, specifies the object to which the iterators' "this" is bound. - - Function#bind and #curry now return the receiving function if the binding object is undefined. - -* Temporary workaround for Prototype.BrowserFeatures.SpecificElementExtensions incorrectly evaluating to true on iPhone. (needs further investigation) [sam] - -* The action for Form#request defaults to the current URL if the "action" attribute is empty. (This is what most of the major browsers do.) Fixes #8483. [Tomas, Mislav Marohnić] - -* In form serialization, change the way submit buttons are handled. Previously all submit buttons were serialized; now Prototype serializes only the first one. Change Form#serialize and Form.serializeElements to accept a params hash. With the "hash: false" option, a serialized string is returned instead of the hash data object. With the "submit: 'foo'" option, only the submit button with the name "foo" is serialized. References #5031. [Mislav Marohnić] - Examples: - $('form').serialize({ submit: 'delete' }) - $('form').serialize({ hash: false }) //-> equivalent to $('form').serialize() - -* Form#findFirstElement respects HTML tabindexes. Closes #7595. [Christophe Porteneuve] - -* Added Form.Element#setValue method for setting values on various form controls. Checkboxes and radio buttons respond to a boolean and multiple select boxes expect an array of values. Closes #5902. [Jonathan Viney, Mislav Marohnić] - Examples: - $('text_input').setValue('hello world!') - $('remember_me').setValue(true) - $('attend_classes').setValue(['cheese rolling', 'evil chemistry']) - -* Make document.getElementsByClassName match a subset of the WHATWG Web Applications 1.0 specification which was adopted in Firefox 3 (http://www.whatwg.org/specs/web-apps/current-work/#getelementsbyclassname). It now supports multiple class names given as a whitespace-separated list in a string. Array argument is not supported. The method will only return the nodes that match all the class names. In browsers that implement the method natively it will not be overwritten. Closes #8401. [Mislav Marohnić] - Example: - document.getElementsByClassName('foo bar') - -* Fix a Safari rendering issue when floating elements could temporarily disappear when opacity was set to 1. Closes #7063. References #3044, #3813, #6706. [Thomas Fuchs, davidjrice] - -* Prevent a crash in Safari when calling String#evalJSON(true) on very large strings. Add String#isJSON. Closes #7834. [Tobie Langel] - -* Prevent a crash in Safari 1.3 on String#stripScripts and String#extractScripts. Closes #8332. [grant, Tobie Langel] - -* Allow JSON data to contain line breaks. Closes #8271. [pijyster, Tobie Langel] - -* Add Hash.prototype.index which returns the first found property that has a specific value. Closes #8528. [Thomas Fuchs, slusarz, Mislav Marohnić] - Examples: - var hash = $H({a:1,b:'2'}); - hash.index(1) // -> 'a' - hash.index('1') // -> undefined - -* Ensure HTMLElement exists before creating Element.extend. [Tobie Langel] - -* Add Number.prototype.round/ceil/floor/abs as an aliases to the respective methods in Math. Refactor to seperate number extensions from base.js. [Thomas Fuchs] - -* Make Element#absolutize and Element#relativize properly use Element#getStyle. Closes #8580. [Christophe Porteneuve] - -* Test library fixes: make rake dist work on Windows, only teardown if a browser is supported. Closes #8463, #8498. [Mislav Marohnić, grant] - -* Change Element.insert syntax to allow multiple positions. [Thomas Fuchs] - Examples: - Element.insert('foo', {top:'bar', bottom:'baz'}); - $('foo').insert({after: new Element('p').update('bar')}); - Element.insert('foo', new Element('p').update('bar')); // defaults to bottom - Element.insert('foo', 'bar'); // defaults to bottom - -* String.prototype.truncate now explicitly converts its return value into a string if no truncation takes place. This prevents possible issues with methods expecting input data that is typeof == 'string'. [Thomas Fuchs, Tobie Langel, Sam Stephenson] - -* Event.findElement behaves as expected when the element passed matches the given selector. Closes #8395. [Mislav Marohnić, Tobie Langel] - -* Element.setOpacity now calls removeAttribute on the filter style on IE if no more filters remain, which makes Cleartype work properly. Closes #8376. [alexdemi, Thomas Fuchs] - -* Event.findElement now uses Element#up (and as a result can take a CSS selector instead of just a tag name). [Tobie Langel] - -* Minor cleanup of the position methods [sam] - -* Fix Element#clonePosition to call viewportOffset. Closes #8372. [graemenelson, Christophe Porteneuve] - -* Prevent an error being thrown by $$ when #id does not exist in $$("div #id"). Closes #8325. [Tobie Langel, ecke] - -* Make Prototype.ScriptFragment behave when including Prototype inline. [Christophe Porteneuve] - -* Deprecate Position (kept for backwards compatibility). Add Element#cumulativeOffset, Element#positionedOffset, Element#absolutize, Element#relativize, Element#cumulativeScrollOffset, Element#getOffsetParent, Element#viewportOffset and Element#clonePosition. [Christophe Porteneuve] - -* Make Element#update and Element#insert work for SELECT tags in IE and Opera. [Tobie Langel] - -* Make Element#insert and Element#update better handle TABLE related elements in IE and Opera. Closes #7776, #8040, #7550, #7776, #7938. [Tobie Langel] - -* Make Element#readAttribute('title') work in Opera. [Tobie Langel] - -* Make Element#replace work with form elements in Firefox and Safari. Closes #8010, #7989. [dsl239, Tobie Langel] - -* Add Element#wrap which wraps the element inside a new one. Closes #5732. [P. Vande, Tobie Langel] - -* Make Element into a constructor: new Element(tagName, attributes). Add Element#writeAttribute which accepts a hash of attributes or a name/value pair. Closes #7476. [Mislav Marohnić, haraldmartin, Tobie Langel] - -* Insertion overhaul: Add Element.insert(content[, position = 'bottom']). Deprecate Insertion (kept for backwards compatibility). Make Ajax.Updater option.insertion accept both Insertion.Top or the now preferred 'top'. Closes #7907. [Tobie Langel] - -* Refactor Element.extend and eliminate Element.extend.cache. [sam] - -* Add Function#curry, Function#delay, Function#defer, and Function#wrap. Closes #8134. [Andrew Dupont, Tobie Langel, sam] - -*1.5.1* (May 1, 2007) - -* Don't duplicate the event argument in Function#bindAsEventListener. Closes #6497. [wiktor] - -* Fix Selector :not-clause chaining. [Andrew Dupont] - -*1.5.1_rc4* (April 27, 2007) - -* Fix $F breakage from [6598]. [sam] - -* Set window.$continue to an Error with a helpful message for anyone who may still be using "throw $continue". [sam] - -* Fix jstest.rb IE support so you don't have to close the IE window after each test (yay!). Closes #8207. [Ryan Schuft] - -* Fix jstest.rb Konqueror support. Closes #7140. [Christophe Porteneuve] - -* Fix regression in which no-argument calls to Element.addMethods() would not add the methods defined in Form.Methods and Form.Element.Methods. Closes #8206. [Tobie Langel, fwittekind] - -* Fix Element#readAttribute to work with the 'type' attribute in IE. Closes #8160. [Tobie Langel, Wiktor Ihárosi] - -*1.5.1_rc3* (April 24, 2007) - -* Add Element#childElements as an alias for Element#immediateDescendants. [Tobie Langel] - -* Optimize DOM navigation methods (Element#up, Element#down, Element#previous, Element#next) for no-argument calls. Closes #7848. [haraldmartin, sam] - -* Add Element#firstDescendant to retrieve the first non-text child node of an element. [sam] - -* Element.addMethods should add methods to Element as well as Element.Methods. Closes #7888. [Andrew Dupont] - -* Add support for per-request onCreate callbacks to Ajax.Request. Closes #8011. [Andrew Dupont] - -* Don't call evalResponse() when an Ajax response has no Content-type header. Closes #7827. [Tobie Langel] - -* Automatically strip security delimiter comments from JSON strings before evaling them. The default delimiter is '/*-secure- ... */' or you can specify your own with the Prototype.JSONFilter regular expression. If you wrap your JSON response bodies in this delimiter on the server side, rogue external sites can't hijack potentially sensitive data via - -### Building Prototype from source ### - -`prototype.js` is a composite file generated from many source files in -the `src/` directory. To build Prototype, you'll need: - -* a copy of the Prototype source tree, either from a distribution tarball or - from the Git repository (see below) -* Ruby 1.8.2 or higher () -* Rake--Ruby Make () -* RDoc, if your Ruby distribution does not include it - -From the root Prototype directory: - -* `rake dist` will preprocess the Prototype source using Sprockets and - generate the composite `dist/prototype.js` -* `rake package` will create a distribution tarball in the - `pkg/` directory - -Contributing to Prototype -------------------------- - -Check out the Prototype source with - - $ git clone git://github.com/sstephenson/prototype.git - $ cd prototype - $ git submodule init - $ git submodule update vendor/sprockets vendor/pdoc vendor/unittest_js - -Find out how to contribute: . - -Documentation -------------- - -Please see the online Prototype API: . diff --git a/Rakefile b/Rakefile deleted file mode 100755 index a0a795150..000000000 --- a/Rakefile +++ /dev/null @@ -1,319 +0,0 @@ -require 'rake' -require 'rake/packagetask' -require 'rbconfig' -require 'yaml' - -module PrototypeHelper - extend Rake::DSL - - ROOT_DIR = File.expand_path(File.dirname(__FILE__)) - SRC_DIR = File.join(ROOT_DIR, 'src') - DIST_DIR = File.join(ROOT_DIR, 'dist') - DOC_DIR = File.join(ROOT_DIR, 'doc') - TEMPLATES_DIR = File.join(ROOT_DIR, 'templates') - PKG_DIR = File.join(ROOT_DIR, 'pkg') - TEST_DIR = File.join(ROOT_DIR, 'test') - TEST_UNIT_DIR = File.join(TEST_DIR, 'unit') - TMP_DIR = File.join(TEST_UNIT_DIR, 'tmp') - VERSION = YAML.load(IO.read(File.join(SRC_DIR, 'constants.yml')))['PROTOTYPE_VERSION'] - - DEFAULT_SELECTOR_ENGINE = 'sizzle' - - host = RbConfig::CONFIG['host'] - IS_WINDOWS = host.include?('mswin') || host.include?('mingw32') - - # Possible options for PDoc syntax highlighting, in order of preference. - SYNTAX_HIGHLIGHTERS = [:pygments, :coderay, :none] - - %w[sprockets pdoc unittest_js caja_builder].each do |name| - $:.unshift File.join(PrototypeHelper::ROOT_DIR, 'vendor', name, 'lib') - end - - def self.has_git? - begin - `git --version` - return true - rescue Error - return false - end - end - - def self.require_git - return if has_git? - puts "\nPrototype requires Git in order to load its dependencies." - puts "\nMake sure you've got Git installed and in your path." - puts "\nFor more information, visit:\n\n" - puts " http://git-scm.com/book/en/v2/Getting-Started-Installing-Git" - exit - end - - def self.sprocketize(options = {}) - options = { - :destination => File.join(DIST_DIR, options[:source]), - :strip_comments => true - }.merge(options) - - require_sprockets - load_path = [SRC_DIR] - - if selector_path = get_selector_engine(options[:selector_engine]) - load_path << selector_path - end - - secretary = Sprockets::Secretary.new( - :root => File.join(ROOT_DIR, options[:path]), - :load_path => load_path, - :source_files => [options[:source]], - :strip_comments => options[:strip_comments] - ) - - secretary.concatenation.save_to(options[:destination]) - end - - def self.build_doc_for(file) - rm_rf(DOC_DIR) - mkdir_p(DOC_DIR) - hash = current_head - index_header = < - - Prototype JavaScript Framework API - - -EOF - PDoc.run({ - :source_files => Dir[File.join('src', 'prototype', '**', '*.js')], - :destination => DOC_DIR, - :index_page => 'README.markdown', - :syntax_highlighter => syntax_highlighter, - :markdown_parser => :bluecloth, - :src_code_text => "View source on GitHub →", - :src_code_href => proc { |obj| - "https://github.com/sstephenson/prototype/blob/#{hash}/#{obj.file}#L#{obj.line_number}" - }, - :pretty_urls => false, - :bust_cache => false, - :name => 'Prototype JavaScript Framework', - :short_name => 'Prototype', - :home_url => 'http://prototypejs.org', - :version => PrototypeHelper::VERSION, - :index_header => index_header, - :footer => 'This work is licensed under a Creative Commons Attribution-Share Alike 3.0 Unported License.', - :assets => 'doc_assets' - }) - end - - def self.require_package(name) - begin - require name - rescue LoadError - puts "You need the #{name} package. Try installing it with:\n" - puts " $ gem install #{name}" - exit - end - end - - def self.require_phantomjs - cmd = IS_WINDOWS ? "phantomjs.cmd -v" : "phantomjs -v > /dev/null 2>&1" - success = system(cmd) - if !success - puts "\nYou need phantomjs installed to run this task. Find out how at:" - puts " http://phantomjs.org/download.html" - exit - end - end - - def self.syntax_highlighter - if ENV['SYNTAX_HIGHLIGHTER'] - highlighter = ENV['SYNTAX_HIGHLIGHTER'].to_sym - require_highlighter(highlighter, true) - return highlighter - end - - SYNTAX_HIGHLIGHTERS.detect { |n| require_highlighter(n) } - end - - def self.require_highlighter(name, verbose=false) - case name - when :pygments - success = system("pygmentize -V > /dev/null") - if !success && verbose - puts "\nYou asked to use Pygments, but I can't find the 'pygmentize' binary." - puts "To install, visit:\n" - puts " http://pygments.org/docs/installation/\n\n" - exit - end - return success # (we have pygments) - when :coderay - begin - require 'coderay' - rescue LoadError - if verbose - puts "\nYou asked to use CodeRay, but I can't find the 'coderay' gem. Just run:\n\n" - puts " $ gem install coderay" - puts "\nand you should be all set.\n\n" - exit - end - return false - end - return true # (we have CodeRay) - when :none - return true - else - puts "\nYou asked to use a syntax highlighter I don't recognize." - puts "Valid options: #{SYNTAX_HIGHLIGHTERS.join(', ')}\n\n" - exit - end - end - - def self.require_sprockets - require_submodule('Sprockets', 'sprockets') - end - - def self.require_pdoc - require_submodule('PDoc', 'pdoc') - end - - def self.require_unittest_js - require_submodule('UnittestJS', 'unittest_js') - end - - def self.require_caja_builder - require_submodule('CajaBuilder', 'caja_builder') - end - - def self.get_selector_engine(name) - return if !name - # If the submodule exists, we should use it. - submodule_path = File.join(ROOT_DIR, "vendor", name) - return submodule_path if File.exist?(File.join(submodule_path, "repository", ".git")) - return submodule_path if name === "legacy_selector" - - # If it doesn't exist, we should fetch it. - get_submodule('the required selector engine', "#{name}/repository") - unless File.exist?(submodule_path) - puts "The selector engine you required isn't available at vendor/#{name}.\n\n" - exit - end - end - - def self.get_submodule(name, path) - require_git - puts "\nYou seem to be missing #{name}. Obtaining it via git...\n\n" - - Kernel.system("git submodule init") - return true if Kernel.system("git submodule update vendor/#{path}") - # If we got this far, something went wrong. - puts "\nLooks like it didn't work. Try it manually:\n\n" - puts " $ git submodule init" - puts " $ git submodule update vendor/#{path}" - false - end - - def self.require_submodule(name, path) - begin - full_path = File.join(PrototypeHelper::ROOT_DIR, 'vendor', path, 'lib', path) - # We need to require the explicit version in the submodule. - require full_path - rescue LoadError => e - # Wait until we notice that a submodule is missing before we bother the - # user about installing git. (Maybe they brought all the files over - # from a different machine.) - missing_file = e.message.sub('no such file to load -- ', '').sub('cannot load such file -- ', '') - if missing_file == full_path - # Missing a git submodule. - retry if get_submodule(name, path) - else - # Missing a gem. - puts "\nIt looks like #{name} is missing the '#{missing_file}' gem. Just run:\n\n" - puts " $ gem install #{missing_file}" - puts "\nand you should be all set.\n\n" - end - exit - end - end - - def self.current_head - `git show-ref --hash HEAD`.chomp[0..6] - end -end - -task :default => [:dist, :dist_helper, :package, :clean_package_source] - -desc "Builds the distribution." -task :dist do - PrototypeHelper.sprocketize( - :path => 'src', - :source => 'prototype.js', - :selector_engine => ENV['SELECTOR_ENGINE'] || PrototypeHelper::DEFAULT_SELECTOR_ENGINE - ) -end - -namespace :doc do - desc "Builds the documentation." - task :build => [:require] do - PrototypeHelper.build_doc_for(ENV['SECTION'] ? "#{ENV['SECTION']}.js" : 'prototype.js') - end - - task :require do - PrototypeHelper.require_pdoc - end -end - -task :doc => ['doc:build'] - -desc "Builds the updating helper." -task :dist_helper do - PrototypeHelper.sprocketize(:path => 'ext/update_helper', :source => 'prototype_update_helper.js') -end - -Rake::PackageTask.new('prototype', PrototypeHelper::VERSION) do |package| - package.need_tar_gz = true - package.package_dir = PrototypeHelper::PKG_DIR - package.package_files.include( - '[A-Z]*', - 'dist/prototype.js', - 'lib/**', - 'src/**', - 'test/**' - ) -end - -task :clean_package_source do - rm_rf File.join(PrototypeHelper::PKG_DIR, "prototype-#{PrototypeHelper::VERSION}") -end - -task :test => ['test:require', 'test:start'] -namespace :test do - desc 'Starts the test server.' - task :start => [:require] do - path_to_app = File.join(PrototypeHelper::ROOT_DIR, 'test', 'unit', 'server.rb') - require path_to_app - - puts "Starting unit test server..." - puts "Unit tests available at \n\n" - UnitTests.run! - end - - task :require do - PrototypeHelper.require_package('sinatra') - end - - desc "Opens the test suite in several different browsers. (Does not start or stop the server; you should do that separately.)" - task :run => [:require] do - browsers, tests, grep = ENV['BROWSERS'], ENV['TESTS'], ENV['GREP'] - path_to_runner = File.join(PrototypeHelper::ROOT_DIR, 'test', 'unit', 'runner.rb') - require path_to_runner - - Runner::run(browsers, tests, grep) - end - - desc "Runs the tests in PhantomJS. (Does not start or stop the server; you should do that separately.)" - task :phantom do - PrototypeHelper.require_phantomjs - tests, grep = ENV['TESTS'], ENV['GREP'] - url = "http://127.0.0.1:4567/test/#{tests}" - url << "?grep=#{grep}" if grep - system(%Q[phantomjs ./test/unit/phantomjs/mocha-phantomjs.js "#{url}"]) - end -end diff --git a/_layouts/blog_archive.html b/_layouts/blog_archive.html new file mode 100644 index 000000000..a650cb490 --- /dev/null +++ b/_layouts/blog_archive.html @@ -0,0 +1,41 @@ + + + + + Prototype Blog: {{ page.title }} + + + +
+ + + + + +
+
+

{{ page.title }}

+

By {{ page.author }} on {{ page.date | date: '%B %e, %Y') }}.

+ {{ content }} +
+ +
+ + + blog comments powered by Disqus +
+ + + + + +
+ + diff --git a/_layouts/default.html b/_layouts/default.html new file mode 100644 index 000000000..2292604bd --- /dev/null +++ b/_layouts/default.html @@ -0,0 +1,25 @@ + + + + + Prototype JavaScript Framework + + + + +
+ + +
+ {{ content }} +
+ + +
+ + diff --git a/_posts/2007-01-18-prototype-documentation-is-here.markdown b/_posts/2007-01-18-prototype-documentation-is-here.markdown new file mode 100644 index 000000000..ebc1d40a8 --- /dev/null +++ b/_posts/2007-01-18-prototype-documentation-is-here.markdown @@ -0,0 +1,43 @@ +--- +layout: blog_archive +author: Justin Palmer +author_url: http://alternateidea.com/ +sections: Releases, blog +title: "Prototype 1.5 and the Documentation is Here" +--- + +Ever since the [initial announcement](http://encytemedia.com/blog/articles/2006/10/31/prototype-a-call-for-documentation) of the documentation effort, we've been busy planning and preparing Prototype for its rebirth. Along with the official 1.5 release, we'd like to welcome you to the official home of Prototype. This site will serve as the center of our community and help developers everywhere become familiar with Prototype and its continued progress. + +### Prototype 1.5 release +We've been [squashing some nasty bugs](http://dev.rubyonrails.org/log/spinoffs/prototype) getting ready for the 1.5 release. You can get the full scoop on all the fixes and improvements in the [CHANGELOG](http://dev.rubyonrails.org/browser/spinoffs/prototype/trunk/CHANGELOG?format=raw). + +### The API gets documentation +While there has always been [some great documentation](http://www.sergiopereira.com/articles/prototype.js.html) on Prototype, we've been the victim of a famous quote from *["The Man Who Shot Liberty Valance"](http://www.imdb.com/title/tt0056217/quotes): + +> When the legend becomes fact, print the legend. + +We're moving past those times, however. We've worked really hard to [fully document the API](/api). This is something we'll be improving over time, but it's a great start. Here are some of the features: + +#### Guessable URLs +The documentation site has guessable URLs. For instance, if you're looking for documentation on `Element.show`, then you can find that documentation at a url like: http://prototypejs.org/api/element/show. If you're looking for `Form.Element.focus` you can find it at: http://prototypejs.org/api/form/element/focus. + +#### Atom feeds +Each Object has its own atom feed. This opens the doors for integrated documentation. For instance, if you want the XML file for `Form.Element`, you can find it at: http://prototypejs.org/feed/api/form/element/atom.xml. This feed will always contain the most up-to-date documentation for `Form.Element`. + +#### Tips and Tutorials +We've also added an [article section](http://prototypejs.org/learn) where you can find tips, tutorials, and a variety of articles for Prototype. We plan on adding many more articles to this area over time, so keep your eyes peeled. + +### A special thanks +We've added three new core members to [our team](http://prototypejs.org/core). Chris, Mislav, and Tobie were already avid contributors to Prototype, and they were the driving force behind the documentation effort. We all worked really hard on it, but these guys deserve most of the credit. + +### Rough around the edges +We're not perfect, so if you catch any spots in the documentation that are incorrect, or if you'd like to improve parts of the documentation shoot one of us an email. We'll try to get an official email posted later so you can send in improvements or additions to the documentation. Until then, please enjoy the site! + +**Update:** [Rails 1.2 has been announced](http://weblog.rubyonrails.org/2007/1/19/rails-1-2-rest-admiration-http-lovefest-and-utf-8-celebrations) and includes Prototype 1.5 with the release! Congrats to the Rails team. + + + + + diff --git a/_posts/2007-01-20-plugging-in-to-the-documentation.markdown b/_posts/2007-01-20-plugging-in-to-the-documentation.markdown new file mode 100644 index 000000000..0ca29201f --- /dev/null +++ b/_posts/2007-01-20-plugging-in-to-the-documentation.markdown @@ -0,0 +1,41 @@ +--- +layout: blog_archive +author: Justin Palmer +author_url: http://alternateidea.com/ +sections: Tools, blog +title: "Plugging In to the Documentation" +--- + +Wow, what an exciting first couple of days. Yesterday alone, we received about 100,000 page views and the responses were overwhelmingly positive. Amongst those responses, we've learned of a couple folks who are working on, or have created, some tools for the documentation. I want to throw out a couple of ideas here, and talk about how developers can make use of the docs. In addition to that, let's find out what tools are already available to help you work with Prototype and JavaScript in general. + +### Atom to the rescue +One of the benefits of using [Mephisto](http://mephistoblog.com) to power this site is the way in which it supports atom feeds. This opens the doors for some great uses of the documentation. Based on the comments we've received, some folks have already started on some tools. + +You can get an atom feed for any section of the Prototype API docs. I've just added the official feed icon on the right side of the title for each *object* page. I have plans to get these pages in [hAtom](http://microformats.org/wiki/hatom) format as well, but that'll come later on. In the meantime, you can get the feeds by clicking the feed icon next to the title. Feed URLs are also guessable. If you wanted to get the feed for `Form.element`, you'd have something like this: + + language: html + http://prototypejs.org/feed/api/form/element/atom.xml + +### On to the tools +Ok, so what about those tools? There are a variety of tools available to help you become a more efficient Prototype and JavaScript developer. Here are some of the ones I'm aware of. + +* **Quick API Search:** One commenter whipped up a quick bookmarklet for quickly accessing pages within the documentation. You can get it by dragging this link to your bookmarks bar. + +#### TextMate Plugins +* **Prototype Snippets and Language Grammar:** [Thomas Aylott](http://subtlegradient.com/) is a [TextMate](http://textmate.org) machine! [Grab his TextMate bundle here](http://subtlegradient.com/articles/2006/07/17/textmate-javascript-prototype-script-aculo-us) chocked full of stuff for Prototype. I also believe he's working on a plugin for TextMate that would allow you to search the docs. Who knows what else he'll throw in there. I'm sure it will be great once he gets it finished. + +* **Lint Checking and Compression:** + Andrew has a nice [plugin for lint checking and compressing your code](http://www.andrewdupont.net/2006/10/01/javascript-tools-textmate-bundle/) (if you like that sort of thing). It's a very handy tool that I abuse daily. + +If you're aware of other tools for Prototype, let me know and I'll post them here. + +### Some ideas to ponder (or take action on) +There are a lot of things we can do with the documentation. Here are some of the things I've been thinking about. + +* Firefox search plugin +* Firefox sidebar +* TextMate tooltips and search +* Integration with other editors (anyone know of something like this already?) + +Technorati Profile + diff --git a/_posts/2007-02-01-a-call-to-prototype-developers.markdown b/_posts/2007-02-01-a-call-to-prototype-developers.markdown new file mode 100644 index 000000000..7dd82ad1f --- /dev/null +++ b/_posts/2007-02-01-a-call-to-prototype-developers.markdown @@ -0,0 +1,56 @@ +--- +layout: blog_archive +author: Tobie Langel +author_url: http://tobielangel.com/ +sections: Tools, blog +title: "A call to Prototype developers" +--- + +In the spirit of our [Who's Using Prototype](/real-world) section, we'd like to add a new section to this site featuring a sample of the best built-with-Prototype third-party libraries available out there. + +As we want to make this useful for Prototype users, rewarding for library developers _and_ maintainable (seriously, how frustrating is it to read the description of a lib and find out that the link to it is broken), we'll keep the number of displayed libraries to a reasonable amount. So there will be some selection. + +We're looking for libraries that: + +* work seamlessly with Prototype 1.5, +* are cross-browser, +* are well-maintained, +* are beautifully crafted, +* meet a real need, and +* are distributed under the [MIT license](http://www.opensource.org/licenses/mit-license.php) (or similar). + +juicy extras (really not required, just highly appreciated): + +* documentation and +* [unit tests](http://wiki.script.aculo.us/scriptaculous/show/UnitTesting) (we _love_ those). + +If you think that you meet these requirements, we'd love to hear about you! All you need to do is fill [this form](http://prototypejs.wufoo.com/forms/builtwithprototype-3rd-party-libs/). + +We're really excited to see what you have cooking. + +### docmania + +Totally unrelated to the above, but too cool not to be mentioned: + +* [Josh Clark](http://www.globalmoxie.com/) has crafted a _superb_ PDF version of the docs which is [available for your downloading pleasure](http://beta.bigmedium.com/projects/prototype-pdf/index.shtml), +* [Wolfgang Bartelme](http://www.bartelme.at/) has designed a [beautiful dashboard widget](http://www.bartelme.at/journal/archive/prototype_reference_widget/) that allows easy access to the Prototype API, +* and, last but not least, [Marius Feraru](http://www.altblue.com/)'s Firefox sidebar is also [available for download](http://gfx.neohub.com/prototype-js-sidebar/). + +Keep it coming! + + + + + + + + + + + + + + + + + diff --git a/_posts/2007-03-09-prototype-1-5-1-rc1.textile b/_posts/2007-03-09-prototype-1-5-1-rc1.textile new file mode 100644 index 000000000..def688a1d --- /dev/null +++ b/_posts/2007-03-09-prototype-1-5-1-rc1.textile @@ -0,0 +1,49 @@ +--- +layout: blog_archive +author: Sam Stephenson +author_url: http://conio.net/ +sections: Releases, blog +title: "Prototype 1.5.1 release candidate" +--- + +The first release candidate for Prototype 1.5.1 is now "available for download":http://prototypejs.org/assets/2007/3/9/prototype.js. Prototype 1.5.1_rc1 contains bug fixes, performance improvements, and a few new features. If you're using Prototype 1.5.0 in your application, we urge you to upgrade to this release candidate and "report any bugs you may encounter":http://prototypejs.org/contribute. Assuming no heinous bugs are found, you can expect the final version to be released sometime within the next couple of weeks. + +Keep reading for an overview of what's changed (or see the full "CHANGELOG":http://dev.rubyonrails.org/browser/spinoffs/prototype/tags/rel_1-5-1_rc1/CHANGELOG?format=raw for more details). + +h3. Bug fixes + +* $$ no longer returns duplicates for certain selectors. "[#7568]":http://dev.rubyonrails.org/ticket/7568 +* Hash#toQueryString no longer doubly encodes certain parameters. "[#7421]":http://dev.rubyonrails.org/ticket/7421 +* $H no longer iterates over shadowed properties in Safari. "[#7421]":http://dev.rubyonrails.org/ticket/7421 +* Form.Element#disable will now call blur(), removed blur() call from Form.Element#enable. "[#6034]":http://dev.rubyonrails.org/ticket/6034 +* Fixed an issue with serializing empty array inputs. "[#7516]":http://dev.rubyonrails.org/ticket/7516 +* Fixed a bug in the simulated hasAttribute for IE due to getAttributeNode sometimes returning null. +* Fixed that Form.Methods and Form.Element.Methods weren't being applied correctly to forms and form elements in Safari. "[#7358]":http://dev.rubyonrails.org/ticket/7358 +* Fixed setStyle with opacity: 0 to work correctly in IE. +* Fixed that Form.Element#activate shouldn't raise an exception when the form or field is hidden. + +h3. New features and changes + +* "$$ now supports virtually all of CSS3":http://prototypejs.org/api/utility/dollar-dollar, with the exception of some pseudo-elements (like ::first-letter) and some pseudo-classes (like :hover). +* Prototype now has support for JSON encoding and decoding built in. If you've had issues with the official json.js library extending Object.prototype, you can now "use our implementation instead":http://prototypejs.org/learn/json. Thanks "Tobie":http://tobielangel.com/! +* Element.extend can now take a tag name or array of tag names as its first argument to apply the given methods to specific tags. +* Added "String#empty":http://prototypejs.org/api/string/empty, "String#blank":http://prototypejs.org/api/string/blank, "String#startsWith":http://prototypejs.org/api/string/startsWith, "String#endsWith":http://prototypejs.org/api/string/endsWith, "String#include":http://prototypejs.org/api/string/include, and "String#times":http://prototypejs.org/api/string/times. +* Added "Number#toPaddedString":http://prototypejs.org/api/number/toPaddedString. +* Added "Form#request":http://prototypejs.org/api/form/request, which uses the form's action and method attributes, along with its serialized parameters, to create an Ajax.Request. +* Removed support for "throw $continue" in Enumerable iterators. If you were using this in your scripts, please replace it with "return" instead. + +h3. Performance improvements + +* $$ is now blazing fast. "Seriously -- try it out.":http://andrewdupont.net/test/double-dollar/ If you're using $$ at all, you owe it to yourself to upgrade! Element#down, Element#up, Element#previous and Element#next received performance boosts too (along with everything else that uses Selector). +* Element#getStyle and Element#setStyle are now faster. +* Array#uniq is faster. "[#7417]":http://dev.rubyonrails.org/ticket/7417 +* String#escapeHTML now uses a cached div and text node, making it much faster. "[#6937]":http://dev.rubyonrails.org/ticket/6937 +* Enumerable iteration is faster now that it incurs only one try/catch block instead of two (as a result of removing support for $continue). + +The $$/Selector improvements come from "Andrew":http://andrewdupont.net/ and "Christophe's":http://tddsworld.com/en/ many hours of work, and were inspired by "Jack Slocum's":http://www.jackslocum.com/ "DomQuery":http://www.jackslocum.com/blog/2007/01/11/domquery-css-selector-basic-xpath-implementation-with-benchmarks/ and "Joe Hewitt's":http://www.joehewitt.com/ "CSS selector-to-XPath translation":http://www.joehewitt.com/blog/ive_noticed_tha.php. Selector is now backed by XPath where available (Firefox and Opera 9), and is optimized to be 5x faster on average than the previous version in browsers without XPath. + +Thanks to everyone who contributed to this release! + +"Download Prototype 1.5.1_rc1":http://prototypejs.org/assets/2007/3/9/prototype.js + + diff --git a/_posts/2007-03-12-release-candidate-2.textile b/_posts/2007-03-12-release-candidate-2.textile new file mode 100644 index 000000000..75bd99328 --- /dev/null +++ b/_posts/2007-03-12-release-candidate-2.textile @@ -0,0 +1,14 @@ +--- +layout: blog_archive +author: Sam Stephenson +author_url: http://conio.net/ +sections: Releases, blog +title: "Release candidate 2" +--- + +"Prototype 1.5.1_rc2 is out":http://prototypejs.org/assets/2007/3/12/prototype.js. This release fixes several bugs in IE and Safari (see the "CHANGELOG":http://dev.rubyonrails.org/browser/spinoffs/prototype/tags/rel_1-5-1_rc2/CHANGELOG?format=raw). Upgrade and keep those bug reports coming! + +And don't miss the "script.aculo.us 1.7.1 beta":http://mir.aculo.us/2007/3/12/script-aculo-us-1-7-1-beta. + + + diff --git a/_posts/2007-03-20-future-proofing-prototype.markdown b/_posts/2007-03-20-future-proofing-prototype.markdown new file mode 100644 index 000000000..ab1ec79d6 --- /dev/null +++ b/_posts/2007-03-20-future-proofing-prototype.markdown @@ -0,0 +1,20 @@ +--- +layout: blog_archive +author: Tobie Langel +author_url: http://tobielangel.com/ +sections: General, blog +title: "Future-proofing Prototype" +--- + +[John Resig](http://ejohn.org), best known for his [jQuery](http://jquery.com/) JavaScript library and his work at Mozilla, has just posted [instructions on testing Prototype against the latest alpha builds of Firefox 3](http://ejohn.org/blog/testing-prototype-with-firefox-3/). + +While this doesn't sound so spectacular at first (nothing prevented you from doing so yourself up to now), it's actually great news for Prototype as it's part of a much larger project recently undertook by Mozilla. + +Mozilla has decided to include the test suites of popular JavaScript libraries _directly inside the Mozilla test system_. This means that the developers working on Firefox 3 will run these test suites on a regular basis, probably before each commit. + +You can [read more about this project](http://ejohn.org/blog/future-proofing-javascript-libraries/) over at John's blog. + +The benefits for Prototype, and for the other libraries which will be included shortly, are obviously huge. We'll be made aware of unavoidable regression bugs really early in the developing process and we'll probably avoid many which could have slipped unnoticed without this undertaking. + +If we're lucky, this initiative will push other browser vendors to jump in the bandwagon. And we'll be there to help them make it possible should they decide to do so. + diff --git a/_posts/2007-04-02-jester-activeresource-for-prototype.markdown b/_posts/2007-04-02-jester-activeresource-for-prototype.markdown new file mode 100644 index 000000000..21b54f799 --- /dev/null +++ b/_posts/2007-04-02-jester-activeresource-for-prototype.markdown @@ -0,0 +1,42 @@ +--- +layout: blog_archive +author: Justin Palmer +author_url: http://alternateidea.com/ +sections: Tools, blog +title: "Jester: ActiveResource for Prototype" +--- + +The folks over at [thoughtbot, inc.](http://thoughtbot.com/) have released [Jester](http://giantrobots.thoughtbot.com/2007/4/2/jester-javascriptian-rest), an almost identical port of Rails' ActiveResource to JavaScript. + + +Here is some sample code showing associations (hijacked directly from the blog post): + + >>> eric = User.find(1) + GET http://localhost:3000/users/1.xml + Object _name=User _singular=user _plural=users + + >>> eric.posts + [Object _name=Post _singular=post _plural=posts, Object _name=Post _singular=post _plural=posts] + + >>> eric.posts.first().body + "Today I passed the bar exam. Tomorrow, I make Nancy my wife." + >>> eric.posts.first().body = "Today I *almost* passed the bar exam. The ring waits one more day." + "Today I *almost* passed the bar exam. The ring waits one more day." + + >>> eric.posts.first().save() + POST http://localhost:3000/posts/1.xml + true + + >>> post = Post.find(1) + GET http://localhost:3000/posts/1.xml + Object _name=Post _singular=post _plural=posts + + >>> post.body + "Today I *almost* passed the bar exam. The ring waits one more day." + >>> post.user + Object _name=User _singular=user _plural=users + >>> post.user.name + "Eric Mill" + +[Hop over to GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS](http://giantrobots.thoughtbot.com/2007/4/2/jester-javascriptian-rest) (cool name eh?) for the full scoop, code, and to give those guys your feedback. + diff --git a/_posts/2007-04-05-firebug-secuirity-update.markdown b/_posts/2007-04-05-firebug-secuirity-update.markdown new file mode 100644 index 000000000..8be1b9738 --- /dev/null +++ b/_posts/2007-04-05-firebug-secuirity-update.markdown @@ -0,0 +1,15 @@ +--- +layout: blog_archive +author: Justin Palmer +author_url: http://alternateidea.com/ +sections: General, blog +title: "Firebug Security Update" +--- + +Joe Hewitt has released an update to Firebug that addresses a Zero Day vulnerability. It's recommended that everyone upgrade if you've got Firebug installed. + +You can read more about [the update on Joe's blog](http://www.getfirebug.com/blog/2007/04/04/security-update/). + +Thanks to Ray Bango for the heads up on this. + + diff --git a/_posts/2007-04-20-rico-rises-from-the-dead.markdown b/_posts/2007-04-20-rico-rises-from-the-dead.markdown new file mode 100644 index 000000000..90002ed92 --- /dev/null +++ b/_posts/2007-04-20-rico-rises-from-the-dead.markdown @@ -0,0 +1,34 @@ +--- +layout: blog_archive +author: Tobie Langel +author_url: http://tobielangel.com/ +sections: blog +title: "Rico rises back from the dead" +--- + +[Rico](http://openrico.org), the Prototype-based UI JavaScript library, just released a first beta of their upcoming version 2.0. + +Here's what's new: + +* **Components:** Rico 2.0 extends the component set from the previous versions. The LiveGrid has been expanded to include filtering, column resizing, and many more features. The core of Rico 2.0 has been designed to enable custom components to be more easily built. + +* **Animation Effects:** Rico 2.0 provides responsive animation for smooth effects and transitions that that can communicate change in richer ways than traditional web applications have explored before. Unlike most effects, Rico 2.0 animation can be interrupted, paused, resumed, or have other effects applied to it to enable responsive interaction that the user does not have to wait on. + +* **Behaviors:** Take some raw HTML and sprinkle in some behaviors and what do you get? Well in Rico you can easily build an Accordion component like those found in Macromedia Flex and Laszlo. + +* **Styling:** Rico provides several cinematic effects as well as some simple visual style effects in a very simple interface. + +* **Drag And Drop:** Desktop applications have long used drag and drop in their interfaces to simplify user interaction. Rico provides one of the simplest interfaces for enabling your web application to support drag and drop. Just register any HTML element or JavaScript object as a draggable and any other HTML element or JavaScript object as a drop zone and Rico handles the rest. + +* **AJAX Support:** Rico provides a very simple interface for registering Ajax request handlers as well as HTML elements or JavaScript objects as Ajax response objects. Multiple elements and/or objects may be updated as the result of one Ajax request. + +Rico 2.0 is based on the latest release of Prototype (currently version 1.5.1_rc2) which is included in the [download](http://openrico.org/downloads). + +I am really, really happy to see this project live again, as yet another example of the striving Prototype community, and possibly one of the best rewards we could get for the work we've put into Prototype 1.5, the upcoming 1.5.1 release and this very website. + +So thank you Richard Cowin for resurrecting Rico and welcome to your new contributor: Matt Brown. + + + + + diff --git a/_posts/2007-04-24-release-candidate-3.markdown b/_posts/2007-04-24-release-candidate-3.markdown new file mode 100644 index 000000000..8fd7c9305 --- /dev/null +++ b/_posts/2007-04-24-release-candidate-3.markdown @@ -0,0 +1,42 @@ +--- +layout: blog_archive +author: Tobie Langel +author_url: http://tobielangel.com/ +sections: Releases, blog +title: "Release candidate 3" +--- + +[Prototype 1.5.1_rc3](http://prototypejs.org/assets/2007/4/24/prototype.js) is out! + +Here's what's new: + +#### Bug fixes + * `Element.addMethods` now again adds the methods to Element. [[#7888]](http://dev.rubyonrails.org/ticket/7888) + * `Form.request` also works with forms containing an input element with `name="action"`. [[#8063]](http://dev.rubyonrails.org/ticket/8063) + * Safari no longer crashes on `String#stripScripts` and `extractScripts` with large ` + + +Or you can use Google's API: + +
+  
+  
+
+ +More information is available from "Google's documentation":http://code.google.com/apis/ajaxlibs/documentation/index.html#prototype. + +When a specific version of Prototype is delivered to your browser, it will be cached for one year and served with the proper compression headers. That means that most users of sites which link to Google's copy of Prototype will incur a ~30 KB download only once. + +We typically encourage developers building applications with Prototype to concatenate all their JavaScript into a single file, and serve that file with the proper content expiration and compression settings. In cases where this is unfeasible, Google's hosted version is an excellent alternative. + +Special thanks to Dion Almaer and the team at Google for making this possible. + + + diff --git a/_posts/2008-05-28-an-interview-with-piotr-dachtera.markdown b/_posts/2008-05-28-an-interview-with-piotr-dachtera.markdown new file mode 100644 index 000000000..c29c30250 --- /dev/null +++ b/_posts/2008-05-28-an-interview-with-piotr-dachtera.markdown @@ -0,0 +1,65 @@ +--- +layout: blog_archive +author: Tobie Langel +author_url: http://tobielangel.com/ +sections: Featured, Interviews, blog +title: "An Interview with Piotr Dachtera" +--- + + + +Piotr Dachtera is the lead developer behind the recently-launched Live Chess, a Prototype-based, Comet-powered live chess game. + +We talked to him about the client-side challenges he faced along the way. + + + +

Hi, Piotr. Could you please introduce yourself?

+ +Piotr Dachtera: Sure. I'm currently the lead developer of the JavaScript/Ajax/Comet part of [chess.com](http://chess.com). + +I've been dedicated to Web + chess applications since 1999. I've also been working on business software since 2000 (mainly [Java](http://java.sun.com/)). My interest in the game of chess was always pushing me forward and finally I think I can say I'm working on the number one web chess project. + +

You've built Live Chess using Prototype and script.aculo.us. Can you tell us more about the application?

+ +PD: Chess community website users need to share things using a specific "language" which needs something more than plain text. They need to share game positions, whole chess games with analysis, and chess puzzles. Also, they want to play against each other. + +Screenshot of Live Chess + +As we were starting to work on it all, I already had some experience with Prototype and script.aculo.us, and it was the natural choice. + +We started with the interactive boards with draggable pieces, chess game parsers and things like that. Naturally, I had in mind that we were going to build something much more complex (the scalable real-time play server), so enclosing everything in reusable classes was the only solution. As it was always tempting to see what's inside Prototype, I was investigating its source all the time and I was trying to build my classes using the same style. + +

Live Chess uses Comet to keep the chessboard synchronized. What made you choose that technology over ordinary Ajax?

+ +PD: The most important word in "Live Chess" is "live." We need things to happen instantly. We can't use polling to check every 10 seconds if anything changed. + +If people want to play a game of chess in 2 minutes, they need some kind of _instant_ communication. + +

Can you give us more details on the Comet implementation?

+ +PD: Working on my own proof-of-concept chess server in 2005, I "(re)invented" the Comet idea to allow this kind of communication... only to find out that people were using the same idea in simple chat apps. + +The next step (which came with the new server built for the chess.com community and needed real scalability) was to use the idea of thread-less server solutions implemented in [Jetty](http://www.mortbay.org/) server and [ActiveMQ](http://activemq.apache.org/) to push messages between client and server. + +Finally, we switched to [Cometd/Bayeux](http://cometd.com/) with our own solution for guaranteed messaging and message ordering. + +In all of these solutions, there was always Java on the server-side. + +

What are you using Prototype for?

+ +PD: I started with script.aculo.us effects investigation which guided me directly to Prototype. + +Currently, I'm not really a JavaScript developer. I'm a Prototype developer using the library everywhere. + +

On top of Prototype and Dojo, I saw you were also using ExtJS in Live Chess. Was the integration of these three libraries seamless or were there issues?

+ +PD: We are using ExtJS with the [Prototype adapter](http://extjs.com/products/extjs/build/) so there was nothing really hard to do here. + +Dojo things are completely separated from the rest of the system, but we had to use the library for Cometd communication. As a Prototype fan, I would be really happy to have a Cometd implementation built on top of Prototype, but currently I had to use Dojo in this area (which is sandboxed in a separate communication frame). + +

What were the biggest challenges you faced with this application?

+ +PD: We still have lots of big challenges! But if I had to choose one, I would say: performance. Everybody wants to use Live Chess (and any other similar application) as if it was a desktop application. +As the system becomes heavier and more complex, we still have to work hard to keep it _smooth_. + diff --git a/_posts/2008-06-11-an-interview-with-ryan-johnson.markdown b/_posts/2008-06-11-an-interview-with-ryan-johnson.markdown new file mode 100644 index 000000000..730ab21b3 --- /dev/null +++ b/_posts/2008-06-11-an-interview-with-ryan-johnson.markdown @@ -0,0 +1,78 @@ +--- +layout: blog_archive +author: Tobie Langel +author_url: http://tobielangel.com/ +sections: Interviews, blog +title: "An Interview with Ryan Johnson" +--- + + + +Today's interviewee is [Ryan Johnson](http://livepipe.net/) of [Control Suite](http://livepipe.net/projects/control_suite/) fame. + +Ryan just launched [PersonalGrid](http://personalgrid.com/), a new file sharing and publishing web application, along with a complete overhaul of Control Suite, now renamed [LivePipe UI](http://livepipe.net/). + +

Hi, Ryan. Could you please introduce yourself.

+ +Ryan Johnson: I've been writing web pages since 1993, but I've only felt comfortable calling myself a programmer for the last 5 years. I drank the Prototype kool-aid about 2 and a half years ago, and I'd say today nearly 75% of all the code I write is JavaScript. I enjoy writing Ruby just as much, but fewer and fewer people are asking me to do any work in Ruby at all. + +The language itself hasn't evolved all that much, but watching our collective knowledge and understanding of it grow has been a surprise and delight. + +

You just released a new web application: PersonalGrid. Can you tell us about it?

+ + +RJ: [PersonalGrid](http://personalgrid.com/) is a file-sharing and publishing application that I've written. You can use it to upload files and publish single files or whole folders with one click. It's also easy to share with friends or whole groups of users. + +We have a dev team of one (me), and this is our first beta release, so hopefully any bugs you encounter won't be too catastrophic. + +

How are you using Prototype in PersonalGrid? And script.aculo.us?

+ +RJ: On the Rails side, 95% of the actions use a REST interface and spit back [JSON](http://json.org), so the app is very client-heavy. Almost all of the HTML is generated with the Prototype [Template](http://prototypejs.org/api/template "Prototype JavaScript framework: Template") class, with a little usage of the [new Element](http://prototypejs.org/api/element) syntax thrown in where appropriate. I used the Draggables and Droppables from script.aculo.us, but little else. I also ended up making many modifications (which I will release on GitHub sometime soon) to both of those classes to support some extra functionality. + +Both Object.Event and LivePipe UI are discussed below, but those libraries are integral to the application. So our JavaScript stack looks like Prototype → LivePipe UI → PersonalGrid Application. The actual PersonalGrid JavaScript code is a number of classes that represent the major UI components (File, Folder, Friend, Group, etc), and a number of controller classes that initiate Ajax requests and process the JSON responses. + +In the process of building the application layer I kept seeing inklings of a JavaScript MVC framework, but I just don't see where the reusability would come from. Prototype is ever more awesome, and I'm releasing components that others will hopefully find useful. + +

What were the biggest challenges you faced when building it?

+ +RJ: Internet Explorer. The only debate about the IE debacle that should be going on is whether the product is a result of incompetence or was designed deliberately to sabotage the development of complex web applications. They got XHR and the mouseenter/mouseleave events right, but that is about it. + +

Any technical advice, tips, or tricks you'd like to share?

+ +RJ: Start using a broadcast/subscription based event model for everything in your app, not just Element objects! Of course I am going to plug my own solution [Object.Event](http://livepipe.net/projects/object_event/) — but whether or not you use that, having a system where you can trigger your own events that do not relate to the DOM is critical for the maintainability of your code base. The new custom events in Prototype 1.6 are great (and I used a few in PersonalGrid), but it's still geared towards the DOM. + +For example, we have a trash can feature in PersonalGrid. Each user's root directory has a `.Trash` folder, which mostly acts like any other folder, but we need to specialize its behavior. The two biggest differences are that we want to take the `.Trash` folder out of the normal directory listing, and give it a special place in the UI. We also want `.Trash` to behave differently when you are in it. We have a Location class that is responsible for changing folders, rending the directory listing, etc. Instead of putting these specializations for the Trash inside the Location class, we have the Location class fire an `onChangeLocation` event, which the Trash class observes. + +It's not only a conceptually elegant way to solve the problem, but you get the added benefit of having all of the code that relates to the Trash in one place. As I was developing the app, we ended up wanting all of these little specializations for friendship folders, group folders, etc, so the broadcast/subscription model has really ended up paying huge dividends as the project progresses. + +

You're using a Java applet for file upload. Why did you choose to use that technology? What are the advantages over using flash?

+ +RJ: There are some problems with the delay in loading the JVM, and the whole certificate/trust issues that all applets have, so I don't want to sound too triumphant about the choice just yet. The main reason I choose Java instead of Flash is that you can drag and drop files onto the applet, which Flash does not support. Leopard supports dragging files directly onto file inputs, but users do not universally expect that behavior yet. + +One of the areas I'd like to explore more is deep interaction between Java/Flash and JavaScript. The Java applet is one of the few parts of PersonalGrid that I didn't write, but I worked closely with our Java coder to create a large series of JavaScript callbacks inside the applet so I could build a UI with Prototype. + +Java applet uploader screenshot + +There are a lot of fairly hairy undocumented bugs with [LiveConnect](http://en.wikipedia.org/wiki/LiveConnect) (the Java/JS bridge), but until we get richer native functionality this is the only way to get around some of the security constrains browsers place on accessing the local machine. + +

You're well known within the Prototype community for Control Suite. Can you tell us a bit more about it? Are you using any of it in PersonalGrid?

+ +RJ: Well I'd like to apologize to the users of Control Suite for neglecting it for the past 8 months! PersonalGrid and some other obligations really destroyed my schedule. Control Suite has just received a major update, and is now called [LivePipe UI](http://livepipe.net/) and is compatible with Prototype 1.6. Most of the complex UI elements you see in PersonalGrid (windows, context menus, selection, etc) are available in the new LivePipe UI release. + +LivePipe UI tries to provide a set of reusable core UI components that has a similar API design philosophy to Prototype. So far only components I have needed are part of the kit, but I am hoping that it grows with time. Now that it is on GitHub I'm hoping that it will be easier for users to contribute. The biggest news to existing users is that the Control.Modal class has been completely rewritten, and it is now a subclass of Control.Window. There are also proper Lightbox and Tooltip classes. The new class system in Prototype 1.6 made that far more elegant than it would have been before. + +

PersonalGrid has a distinct Mac feel. What made you aim for a desktop-like application?

+ +RJ: Since an application of this nature is all about finding and organizing files and folders, why not recreate an interface people are already completely familiar with? We have a ways to go to catch up feature wise to [Box.net](http://box.net), but when I first used their service I noticed they used some desktop metaphors (like drag and drop), but overall the application still felt too much like a website. Plenty of web services **should** feel like websites, but I don't think file management apps should (except for [Drop.io](http://drop.io), which is wonderfully simple). + +PersonalGrid screenshot + + +With regards to the Mac feel... besides borrowing some of the icons (still wondering if we will hear from Apple legal), there are a lot of very particular things that I like about the Finder. One of the hidden features of the PersonalGrid UI is that if you pick up an item and hover over any folder, breadcrumb, group or friendship, you will navigate to that location, and you will still be able to drop the item in any sub folder at the new location. The Finder does this, but I rarely use it because you can have multiple Finder windows open, or use the column view. In a two paned interface it's the only way to elegantly get an item from A to C without moving it to B first. + +Rich web development is still in its infancy, but Apple (and others) have had many complex UI problems elegantly solved for years on the desktop, so when I would run into a brick wall like the A-to-C problem, I would see how it was solved in the Finder, or even read the documentation in the [Human Interface Guidelines](http://developer.apple.com/documentation/UserExperience/Conceptual/OSXHIGuidelines/XHIGIntro/chapter_1_section_1.html). + +It was also an amazingly fun challenge to deconstruct and recreate something as basic as the selection for the new [Control.Selection](http://livepipe.net/control/selection) library, which is also one of the core components of the PersonalGrid UI. When building something that complex yet fundamental one realizes all of the tweaks that coders and designers before you have thought obsessively about. + + + diff --git a/_posts/2008-07-14-announcing-new-prototype-support-mailing-list.markdown b/_posts/2008-07-14-announcing-new-prototype-support-mailing-list.markdown new file mode 100644 index 000000000..2d9351dc6 --- /dev/null +++ b/_posts/2008-07-14-announcing-new-prototype-support-mailing-list.markdown @@ -0,0 +1,14 @@ +--- +layout: blog_archive +author: Andrew Dupont +author_url: http://andrewdupont.net/ +sections: blog +title: "Announcing new Prototype support mailing list" +--- + +Subscribers to the Rails Spinoffs mailing list should switch to our new, better-named list: Prototype & script.aculo.us. + +While these two venerable libraries are, in truth, spinoffs of the Rails project, we've come to realize it's far more user-friendly to have the libraries' names in the name of the mailing list. This should help guide users to the right spot and reduce the amount of support traffic on the Prototype Core mailing list — which is for discussion of Prototype's development process, not support. + +Because list spam is a sad reality, your first post to the list will be held for moderation. Once it's approved, though, you'll be able to post with impunity. + diff --git a/_posts/2008-07-25-first-prototype-developer-day-monday-september-29-2008.textile b/_posts/2008-07-25-first-prototype-developer-day-monday-september-29-2008.textile new file mode 100644 index 000000000..042492ee8 --- /dev/null +++ b/_posts/2008-07-25-first-prototype-developer-day-monday-september-29-2008.textile @@ -0,0 +1,45 @@ +--- +layout: blog_archive +author: Christophe Porteneuve +author_url: http://www.tddsworld.com/en/ +sections: Featured, blog +title: "First Prototype Developer Day: Monday September 29, 2008!" +--- + + + +Prototype Core is happy to announce the first Prototype Developer Day! The Prototype Developer Day is going to be a recurring event bringing together Prototype Core members and users from the Prototype community to share experiences, offer insight into what's coming up, and discuss topics like contribution, support, and the Prototype ecosystem. If you're big on Prototype, you cannot miss this! + +This fall, the Prototype Developer Day is being held in conjunction with "The Ajax Experience":http://ajaxexperience.techtarget.com, held in Boston from Monday, September 29 to Wednesday, October 1 2008. The Prototype Developer Day itself will happen on Monday. + +*Admission to the Developer Day is free*. If you’re interested in attending the full three days of The Ajax Experience, you can *save $100 with the code @Prototype@*. Register before August 22nd and *save an additional $100*. + +The provisional agenda for this Prototype Developer Day is as follows (more details coming up on the "full agenda":http://ajaxexperience.techtarget.com/east/html/eventsataglance.html?Offer=AEprot717): + + + +table(#pddAgenda). +|_.Start time|_.End time|_.Session|_.Speaker| +|8:00am|8:30am|Intro/Welcome|Prototype Core| +|8:30am|9:30am|Contributing docs|Christophe Porteneuve| +|9:30am|9:45am|\2.Break| +|9:45am|9:50am|Greeting|Framework Summit Sponsor| +|9:50am|10:30am|Contributing code|Andrew Dupont| +|10:30am|11:15am|The Prototype ecosystem|TBD| +|11:15am|11:30am|\2.Break| +|11:30am|1:00pm|Extended Q&A|Prototype Core| + +You will get a chance to hook up with members of Prototype Core and "close core", and we all look forward to meeting you guys. Here's the current rundown: + +* Sam Stephenson _(to be confirmed)_ +* Andrew Dupont _(confirmed)_ +* Juriy "kangax" Zaytsev _(confirmed)_ +* Mislav Marohnić _(to be confirmed)_ +* Tobie Langel _(to be confirmed)_ +* Christophe Porteneuve _(confirmed)_ + +For more information on coming with a group, contact "Tracey West":mailto:%22Tracey%20West%22%20%3Ctwest%40techtarget.com%3E?subject=Group%20pricing%20for%20TAE. You can view the "agenda":http://ajaxexperience.techtarget.com/east/html/eventsataglance.html?Offer=AEprot717 for The Ajax Experience, and then proceed to one or both of the following: + +* Want to register for PDD? You *must* use our special "quick form":http://devdays.prototypejs.org. Registering for TAE *doesn't* automatically sign you up for PDD, and the number of seats is pretty limited. (But, hey, there's a free lunch!) +* "Register for The Ajax Experience":http://www.regonline.com/ajaxexperience. + diff --git a/_posts/2008-08-11-practical-prototype-and-scriptaculous.markdown b/_posts/2008-08-11-practical-prototype-and-scriptaculous.markdown new file mode 100644 index 000000000..70b729d56 --- /dev/null +++ b/_posts/2008-08-11-practical-prototype-and-scriptaculous.markdown @@ -0,0 +1,24 @@ +--- +layout: blog_archive +author: Tobie Langel +author_url: http://tobielangel.com/ +sections: Featured, blog, books +title: "Practical Prototype and script.aculo.us" +--- + + +We're very happy to announce a new addition to the Prototype bookshelf: core committer [Andrew Dupont](http://andrewdupont.net/)'s [Practical Prototype and script.aculo.us](http://www.apress.com/book/view/1590599195) published by Apress. + + + +Obviously, [Practical Prototype and script.aculo.us](http://www.apress.com/book/view/1590599195) covers all you need to know about the latest versions of Prototype and script.aculo.us. But it goes well beyond that. Andrew does an awesome job at setting the context and giving appropriate background information, so much so that you'll end up knowing not only the _how_ but also the _why_. In the ruthless world of client-side development, that's a serious asset! + +[Practical Prototype and script.aculo.us](http://www.apress.com/book/view/1590599195) is a pleasure to read -- the style is both straightforward _and_ witty -- and should appeal to beginners and seasoned developers alike. + +If you want to try before you buy, you can always download a [sample chapter](http://www.apress.com/book/downloadfile/4037) or the [table of contents](http://www.apress.com/book/downloadfile/4038) from the Apress website. Or you can grab a hard copy and/or a pdf from the [Apress website](http://www.apress.com/book/view/1590599195) or from [Amazon](http://www.amazon.com/Practical-Prototype-script-aculo-us-Experts-Development/dp/1590599195/). + +As always, happy Prototyping! + + + + diff --git a/_posts/2008-09-30-prototype-1-6-0-3-one-more-bugfix-release-before-1-6-1.markdown b/_posts/2008-09-30-prototype-1-6-0-3-one-more-bugfix-release-before-1-6-1.markdown new file mode 100644 index 000000000..b32bad18a --- /dev/null +++ b/_posts/2008-09-30-prototype-1-6-0-3-one-more-bugfix-release-before-1-6-1.markdown @@ -0,0 +1,45 @@ +--- +layout: blog_archive +author: Andrew Dupont +author_url: http://andrewdupont.net/ +sections: Featured, Releases, blog +title: "Prototype 1.6.0.3: A long-awaited bugfix release" +--- + +

Yesterday we released Prototype 1.6.0.3, the result of some much-needed bug fixes, and a stopgap release on the road to 1.6.1.

+ +

It’s a backwards-compatible, drop-in replacement recommended for all users of Prototype 1.6. We’ve fixed 30 bugs and made 25 other improvements to our already-rock-solid library.

+ +

Developers who follow along in Git might’ve noticed that the repository has seen a lot of disruptive activity in the last few days as we reassessed many of the commits that had gone into the library since April. Rather than try to fit too many fixes into one release, we decided to scale back and release 1.6.0.3 with the set of improvements we were in complete agreement on.

+ +

Because of the way we handled this overhaul, those who try to update their Git working copies to the latest trunk will encounter conflicts, even if they hadn’t made local changes.

+ +

Here’s how we recommend bringing your working copy up to date:

+ +
    +
  1. First, if you’ve made any local changes, please create a new branch so that those changes aren’t lost.
  2. +
  3. On your local master branch, run:

    +
    git fetch origin master
    +git reset --hard 34ee207
    +

    The first line fetches the new commits without trying to apply them to your local copy. The second line resets your master branch to be in sync with the latest revision.

    +
  4. +
  5. From there, you can cherry-pick from your branch any local commits you made (though you may have to do some manual merging).
  6. +
+ + + +

Download, report bugs, and get help

+ + + + + +

As always, thanks to the core team and the many users who contributed bug reports and well-tested patches for this release.

+ + + diff --git a/_posts/2008-10-07-growing-the-community.markdown b/_posts/2008-10-07-growing-the-community.markdown new file mode 100644 index 000000000..a312c83f3 --- /dev/null +++ b/_posts/2008-10-07-growing-the-community.markdown @@ -0,0 +1,56 @@ +--- +layout: blog_archive +author: Andrew Dupont +author_url: http://andrewdupont.net/ +sections: Featured, blog +title: "Growing the community" +--- + +

Now that 1.6.0.3 is out, let’s talk about the Prototype community.

+ +

A lot of people have been commenting on how quiet it’s been around here over the last few months. There are several reasons:

+ + + +

These aren’t excuses; they’re just explanations. As a team, we agree that we’ve got to prevent such a long release gap from happening again, and to keep an eye out for warning signs like the ones listed above.

+ +

This means, among other things, that we’re planning to move away from a “when it’s ready” release schedule. Instead, we’ll move toward one in which there are several releases per year; whatever is ready in time for a given release will go in, and whatever is not will have to wait. That applies to bug fixes and features alike. Eight months between releases just won’t work.

+ +

What you can do

+ +

Community outreach was one of the major goals of Prototype Developer Day. Many people are frustrated with the state of the Prototype community and would like to see some changes made. We’re in complete agreement.

+ +

Ideally, as an open-source community grows, those who want to help out gravitate toward specific roles. Those who can grok the source code write patches; those who are good at diagnosing problems file bug reports; those who can write clearly contribute documentation; and so on. We’d love to grow that “halo” around Prototype Core so that things can get done more quickly.

+ +

To be more specific, we would love help in any of these areas:

+ +
    +
  1. Give support on the Prototype & scrip.aculous mailing list.
  2. +
  3. File bugs in Lighthouse when you encounter errors or surprising behavior in Prototype.
  4. +
  5. Write test cases or patches for existing bugs in Lighthouse.
  6. +
  7. Discuss the direction of the library and its future on the Prototype Core mailing list.
  8. +
  9. Propose new features and implement them.
  10. +
  11. Write documentation wherever you feel we need more; submit it to Lighthouse as an enhancement.
  12. +
  13. Suggest blog posts. (Or even write them!) Post to the Prototype Core list if you’re interested in doing this.
  14. +
+ +

There are, of course, many other things one can do to help us out. But if you’re looking for a way to contribute and don’t have something specific in mind, we’d suggest doing one of these seven things.

+ +

What we can do

+ +

We know we need more help, but we also know we need to be better community curators. So here are some things we pledge to do better:

+ +
    +
  1. We’ll beef up the Prototype web site so that it’s easier to get started with the framework, easier to find great resources like Scripteka and Prototype UI, and easier to find answers to common questions.
  2. +
  3. We’ll give special attention to documentation tickets on Lighthouse so that our API docs don’t stay stale and thin.
  4. +
  5. We’ll release on a more consistent schedule, as explained above.
  6. +
  7. We’ll resume work on PDoc (inline documentation) and Sprockets (JS dependency management), spin-off projects that make Prototype more of a “platform.” They’ll be a boon to the Prototype ecosystem when they’re completed.
  8. +
+ +

Finally: if you consider yourself to be good at planning and organizing an open-source project, then we’d love your input on how to grow our community. Our highest priority, however, is not to launch a new initiative or process; it’s to get more people doing the seven things listed above.

+ + diff --git a/_posts/2008-10-07-want-your-code-pimped.markdown b/_posts/2008-10-07-want-your-code-pimped.markdown new file mode 100644 index 000000000..c22434828 --- /dev/null +++ b/_posts/2008-10-07-want-your-code-pimped.markdown @@ -0,0 +1,27 @@ +--- +layout: blog_archive +author: Andrew Dupont +author_url: http://andrewdupont.net/ +sections: blog +title: "Want your code \"pimped\"?" +--- + +

We decided it’s finally time to implement an idea we had long ago.

+ +

I’m an avid reader of the blog of Wil Shipley, a man in the business of writing great apps for OS X. His running code improvment series, Pimp My Code, takes submissions from readers who think their code needs refactoring. Then Shipley refactors them, explaining the whys and hows along the way. The submissions are small (never more than 75-100 lines), but in rewriting them Shipley always happens upon specific, useful programming tips. I don’t know the first thing about Objective-C, but I find the series fascinating and instructive.

+ +

So we’re going to do something similar on this blog. Do you have a piece of JavaScript you want refactored? Does it use Prototype? Do this:

+ +
    +
  1. Sign up for a GitHub account if you don’t have one. It’s free and quick.
  2. +
  3. Go to Gist, GitHub’s pastebin app, and paste the code you want us to refactor. Mark it as “private” if you like.
  4. +
  5. Message me on GitHub with the URL to your code snippet. If necessary, explain a bit about what the code does (or should do), but don’t write an epistle or anything.
  6. +
+ +

I’ll share the submissions with the rest of the team and we’ll pick a few that we like. Then we’ll dedicate a post to each one, refactoring out loud along the way. We won’t be mean or snarky; this is not a DailyWTF-style exercise.

+ +

To pre-empt the obvious rebuttal: we do not consider this to be an act of charity, or code manna from computer heaven, or a gift from the light-bearers to the huddled masses. Whether we actually “improve” your code is not for us to say. It will, however, illustrate our coding style.

+ +

If that sounds useful to you, then step up! Give us code and ask that it be pimped!

+ + diff --git a/_posts/2008-10-17-prototype-linkedin-group.markdown b/_posts/2008-10-17-prototype-linkedin-group.markdown new file mode 100644 index 000000000..4bd0559e8 --- /dev/null +++ b/_posts/2008-10-17-prototype-linkedin-group.markdown @@ -0,0 +1,20 @@ +--- +layout: blog_archive +author: Tobie Langel +author_url: http://tobielangel.com/ +sections: blog +title: "Prototype Linkedin Group" +--- + +When we first [launched](http://prototypejs.org/2008/5/6/prototype-linkedin-group) the [Linkedin Prototype Group](http://www.linkedin.com/e/gis/99273/13A82A188D9E), we weren't necessarily expecting it to be such a success--it's over 800 members strong and counting. + +Also, at the time, there wasn't much you could do after having joined the group. This has changed with the recent introduction of discussions. + +[One of the first posts](http://www.linkedin.com/groupAnswers?viewQuestionAndAnswers=&gid=99273&discussionID=196323) spurred some thoughts about the usefulness and goals of this Linkedin group especially given the high quality of our [new mailing list](http://groups.google.com/group/prototype-scriptaculous). (And let me take the opportunity to sincerely thank [T.J. Crowder](http://crowdersoftware.com/) for all the effort he's put into it.) + +My initial reaction, based on [an early August thread](http://groups.google.com/group/prototype-scriptaculous/browse_thread/thread/efc72972db79650e) was to suggest keeping the development-orientated discussions in the mailing list, while expecting more career-orientated ones to take place in the Linkedin group. + +Of course, there's no way we can nor should be controlling this, and in the end, you will be deciding what will happen where. So I suppose the only real _raison d'être_ of this post is to advise you of this new feature and open up the debate. + +Thoughts ? + diff --git a/_posts/2009-02-16-pimp-my-code-1-element-storage.markdown b/_posts/2009-02-16-pimp-my-code-1-element-storage.markdown new file mode 100644 index 000000000..ee0db2565 --- /dev/null +++ b/_posts/2009-02-16-pimp-my-code-1-element-storage.markdown @@ -0,0 +1,196 @@ +--- +layout: blog_archive +author: Andrew Dupont +author_url: http://andrewdupont.net/ +sections: blog +title: "Pimp My Code #1: Element.Storage" +--- + +

Man, it's quiet around here. Interested in doing some pimpin'?

+ +

WAIT! COME BACK.

+ +

Code pimping. You know? The thing I'd discussed before? Forgive my earlier informality. I see now how my words could have been confusing.

+ +

The very first edition of Pimp My Code is special because the code we’ll be looking at will be included in Prototype 1.6.1. (It's a bit like if we were to Pimp [someone's] Ride™, then decide to keep the car for ourselves.) So this is more than just an academic exercise for us — the “pimped” result is now part of the Prototype source code.

+ +

The Original

+ +

The code in question, from Sébastien Grosjean (a.k.a. ZenCocoon), implements element “storage” — attaching of arbitrary data to DOM nodes in a safe and leak-free manner. Other frameworks have had this for a while; jQuery’s $.fn.data, for instance, is used heavily by jQuery plugin authors to great effect. But Seb’s is based on the similar Mootools API, which I’ve admired since it debuted in Mootools 1.2.

+ +

Here’s Seb’s code. It’s a long code block, since he’s been thoughtful enough to comment the hell out of it:

+ + + +

The idea is this: instead of storing arbitrary objects as properties on DOM nodes, create one custom property on the DOM node: an index to a global hashtable. The value of that key in the table will itself be a collection of custom key/value pairs. On top of avoiding nasty IE memory leaks (circular references between DOM objects and JS objects), this has the benefit of encapsulating all of an element’s custom metadata into one place.

+ +

Let’s make a first pass at this, line-by-line.

+ +

The Critique

+ +Object.extend(Prototype, {UID: 1}); + +

Already we’ve gotten to something I’d change. Seb is using the Prototype namespace correctly here, in that he’s storing something that’s of concern only to the framework and should feel “private.” But my own preference is to move this property into the Element.Storage namespace. I am fickle and my mind is hard to read.

+ + Element.Storage = { + get: function(uid) { + return (this[uid] || (this[uid] = {})); + }, + + init: function(item) { + return (item.uid || (item.uid = Prototype.UID++)); + } + } + +

OK, another change jumps out at me. The Element.Storage.init method gets called in both Element#store and Element#retrieve; it handles the case where an element doesn’t have any existing metadata. It creates our custom property on the node and increments the counter.

+ +

In other words, store and retrieve are the only two places where this method is needed, so I balk at making it public. My first instinct was to make it a private method inside a closure:

+ + (function() { + function _init(item) { + return (item.uid || (item.uid = Prototype.UID++)); + } + + // ... rest of storage code + })(); + +

I started down this path but quickly stopped. Instead, we’re going to refactor this part so that the init case is handled without the need for a separate method. Let’s move on for now.

+ + Element.Methods.retrieve = function(element, property, dflt) { + if (!(element = $(element))) return; + if (element.uid == undefined) Element.Storage.init(element); + var storage = Element.Storage.get(element.uid); + var prop = storage[property]; + if (dflt != undefined && prop == undefined) + prop = storage[property] = dflt; + return prop; + }; + +

A few things to mention here.

+ + + +

Man, I’m a bastard, aren’t I? Luckily, Element#store is similar enough that there’s no new feedback to be given here, so I’m done kvetching.

+ +

Before we rewrite this code to reflect the changes I’ve suggested, we’re going to make a couple design decisions.

+ +

Feature Design

+ +

While I was deciding how to replace Element.Storage.init, I had an idea: rather than use ordinary Objects to store the data, we should be using Prototype’s Hash. In other words, we’ll create a global table of Hash objects, each one representing the custom key-value pairs for a specific element.

+ +

This isn’t just a plumbing change; it’s quite useful to be able to deal with the custom properties in a group rather than just one-by-one. And since Hash mixes in Enumerable, interesting use cases emerge: e.g., looping through all properties and acting on those that begin with a certain “namespace.”

+ +

So let’s envision a new method: Element#getStorage. Given an element, it will return the Hash object associated with that element. If there isn’t one, it can “initialize” the storage on that element, thus making Element.Storage.init unnecessary.

+ +

This new method also establishes some elegant parallels: the store and retrieve methods are really just aliases for set and get on the hash itself. Actually, retrieve will be a bit more complicated because of the “default value” feature, but we’ll be able to condense store down to two lines.

+ +

The Rewrite

+ +

Enough blathering. Here’s the rewrite:

+ + Element.Storage = { + UID: 1 + }; + +

As promised, I’ve moved the UID counter. The Element.Storage object also acts as our global hashtable, but all its keys will be numeric, so the UID property won’t get in anyone’s way.

+ +

Element#getStorage assumes the duties of Element.Storage.get and Element.Storage.init, thereby making them obsolete. We’ve removed them.

+ + Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + if (Object.isUndefined(element._prototypeUID)) + element._prototypeUID = Element.Storage.UID++; + + var uid = element._prototypeUID; + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + +

The new getStorage method checks for the presence of _prototypeUID. If it’s not there, it gets defined on the node.

+ +

It then looks for the corresponding Hash object in Element.Storage, creating an empty Hash if there’s nothing there.

+ +

As I said before, Element#store is much simpler now:

+ + store: function(element, key, value) { + if (!(element = $(element))) return; + element.getStorage().set(key, value); + return element; + }, + +

I thought about returning the stored value, to make it behave exactly like Hash#set, but some feedback from others suggested it was better to return the element itself for chaining purposes (as we do with many methods on Element).

+ +

And Element#retrieve is nearly as simple:

+ + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + + var hash = element.getStorage(), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + } + }); + +

And we’re done.

+ +

Further refinements

+ +

In fact, we’re not done. This is roughly what the code looked like when I first checked in this feature, but some further improvements have been made.

+ +

Since we’d been using a system similar to this to associate event handlers with nodes, we had to rewrite that code to use the new storage API. In doing so, we found that we needed to include window in our storage system, since it has events of its own. Rather than define a _prototypeUID property on the global object, we give window a UID of 0 and check for it specifically in Element#getStorage.

+ +

Also, based on an excellent suggestion, we changed Element#store so that it could accept an object full of key/value pairs, much like Hash#update.

+ +

In Summation

+ +

I was happy to come across Sébastien's submission. It was the perfect length for a drive-by refactoring; it made sense as a standalone piece of code, without need for an accompanying screenshot or block of HTML; and it implemented a feature we'd already had on the 1.6.1 roadmap.

+ +

You can get the bleeding-edge Prototype if you want to try out the code we wrote. Or you can grab this gist if you want to drop the new functionality in alongside 1.6.0.3.

+ +

We're further grateful to Mootools for the API we're stealing. And to Wil Shipley for the recurring blog article series we're stealing.

+ + diff --git a/_posts/2009-02-20-sprockets-beautiful-and-angular.markdown b/_posts/2009-02-20-sprockets-beautiful-and-angular.markdown new file mode 100644 index 000000000..877eff5e2 --- /dev/null +++ b/_posts/2009-02-20-sprockets-beautiful-and-angular.markdown @@ -0,0 +1,29 @@ +--- +layout: blog_archive +author: Andrew Dupont +author_url: http://andrewdupont.net/ +sections: Featured, blog +title: "Sprockets: Beautiful and angular" +--- + +

Over at SvN, Sam announced the 1.0 release of Sprockets, the new dependency management and concatenation tool that makes it easy to modularize your JavaScript. Sprockets is Prototype’s new build system, but it’s also been extracted into a Ruby library so you can use it anywhere you write JavaScript.

+ +

There are many great ways to use Sprockets in your own projects. You can use it the way Prototype does — split up your JavaScript into small, maintainable files, then create “meta-files” that include the smaller files in a logical order. Prototype had previously been doing this with plain ERB; now we integrate Sprockets as a Git submodule and use it to build our distributable file.

+ +

Sprockets can also be used to write JavaScript “plugins”: bundles of files that can easily be integrated into existing code. With Sprockets, you can formally declare that foo.js depends on thud.js; when your files are concatenated into one output file, thud.js will be included first.

+ +

In addition, Sprockets lets JavaScript files provide other assets — HTML, CSS, images, and the like. At build time, those assets will be copied into the document root of your server (in a way that preserves the sub-structure of directories within). This allows the plugin to refer to those assets via absolute URLs, instead of having to ask you where they’re located.

+ +

A few facts are worth special mention.

+ + + +

In short, we’re excited about what Sprockets means for the Prototype ecosystem. If you maintain a Prototype add-on library, the prototype-core mailing list would love to help you make it Sprockets-aware.

+ +

Now is the time on Sprockets when we dance.

+ + diff --git a/_posts/2009-03-27-prototype-1-6-1-rc2-ie8-compatibility-element-storage-and-bug-fixes.markdown b/_posts/2009-03-27-prototype-1-6-1-rc2-ie8-compatibility-element-storage-and-bug-fixes.markdown new file mode 100644 index 000000000..b6f220674 --- /dev/null +++ b/_posts/2009-03-27-prototype-1-6-1-rc2-ie8-compatibility-element-storage-and-bug-fixes.markdown @@ -0,0 +1,45 @@ +--- +layout: blog_archive +author: Andrew Dupont +author_url: http://andrewdupont.net/ +sections: Featured, Releases, blog +title: "Prototype 1.6.1 RC2: IE8 compatibility, Element storage, and bug fixes" +--- + +Today we tagged the first public release candidate of Prototype 1.6.1. (What happened to RC1? Long story.) While there are more minor fixes we’d like to get into this release, we decided an interim release was necessary because of the final release of Internet Explorer 8 last week. + +

This is the first public release of Prototype that is fully compatible — and fully optimized for — Internet Explorer 8’s “super-standards” mode. In particular, Prototype now takes advantage of IE8’s support of the Selectors API and its ability to extend the prototypes of DOM elements.

+ +

What’s new?

+ + + +

What’s been improved?

+ + + +

Consult the CHANGELOG for more details.

+ +

In addition to the code itself, the 1.6.1 release features Prototype’s embrace of two other excellent projects we’ve been working on: Sprockets (JavaScript concatenation) and PDoc (inline documentation). Sprockets is now used to “build” Prototype into a single file for distribution. PDoc will be the way we document the framework from now on. The official API docs aren’t quite ready yet, but they’ll be ready for the final release of 1.6.1.

+ +

Download, Report Bugs, and Get Help

+ + + +

Thanks to the many contributors who made this release possible!

+ + diff --git a/_posts/2009-06-16-prototype-1-6-1-rc3-chrome-support-and-pdoc.markdown b/_posts/2009-06-16-prototype-1-6-1-rc3-chrome-support-and-pdoc.markdown new file mode 100644 index 000000000..3944bc18e --- /dev/null +++ b/_posts/2009-06-16-prototype-1-6-1-rc3-chrome-support-and-pdoc.markdown @@ -0,0 +1,42 @@ +--- +layout: blog_archive +author: Andrew Dupont +author_url: http://andrewdupont.net/ +sections: Featured, Releases, blog +title: "Prototype 1.6.1 RC3: Chrome support and PDoc" +--- + +Today we’re announcing Release Candidate 3 of Prototype 1.6.1. Among the highlights of this release are official Chrome support, improved IE8 compatibility, faster generation of API documentation with PDoc, and lots of bug fixes. + +

Chrome support

+ +

Since Google Chrome is a close sibling of Safari, Prototype has had excellent Chrome compatibility ever since the browser was first released. Now we’re making it official: Prototype supports Chrome 1.0 and greater.

+ +

If you have Chrome installed on your system (Windows only for now, even though early alphas exist for Mac), invoking rake test will run the unit tests in all locally-installed browsers, including Chrome. To run the unit tests in Chrome alone, try rake test BROWSERS=chrome.

+ +

Generate your own docs with PDoc

+ +

It’s been a long, strange trip for PDoc, the inline-doc tool that will soon be for Prototype and script.aculo.us what RDoc is for Rails. It started as Tobie’s brainchild over a year ago, but key contributions from James Coglan and Samuel Lebeau have helped to carry it across the finish line.

+ +

PDoc was a part of RC2, but has since been updated to make doc generation much, much faster. On my machine, a process that used to take 20 minutes now takes only 60 seconds. Furthermore, we’ve solved a couple of minor issues that made it hard to build the docs on Windows.

+ +

Ever since Prototype 1.5, we’ve kept our documentation in Mephisto, the same engine that powers the rest of the site (and this blog). It’s served us well, but it meant that updating the docs became a chore that could only be started once we’d released a particular version. PDoc will make it far easier to maintain our documentation — and far easier to keep archival copies of the docs for older versions of Prototype.

+ +

Upon final release of 1.6.1, we’ll put the generated docs on this site, just like Rails hosts its most recent stable documentation. Until then, you can generate your own local docs by checking out the full source and running rake doc from the command line.

+ +

Other improvements

+ +

There have also been a number of bugs fixed since RC2 — including a heinous bug relating to Event#observe — and a number of key optimizations. We’ve further improved IE8 compatibility, solving some edge-case issues that popped up since RC2. Credit goes to Juriy (kangax), our newest team member, for working tirelessly these last few months to make 1.6.1 faster and less reliant on browser sniffs.

+ +

Download, report bugs, and get help

+ + + +

Thanks to the many contributors who made this release possible!

+ + diff --git a/_posts/2009-09-01-core-team-update-andrew-and-tobie-take-the-reins.textile b/_posts/2009-09-01-core-team-update-andrew-and-tobie-take-the-reins.textile new file mode 100644 index 000000000..4e1a22304 --- /dev/null +++ b/_posts/2009-09-01-core-team-update-andrew-and-tobie-take-the-reins.textile @@ -0,0 +1,14 @@ +--- +layout: blog_archive +author: Sam Stephenson +author_url: http://conio.net/ +sections: blog +title: "Core Team update: Andrew & Tobie take the reins" +--- + +In addition to [releasing Prototype 1.6.1](http://prototypejs.org/blog/2009/9/1/prototype-1-6-1-released), I'm pleased to announce that Andrew Dupont and Tobie Langel now officially head up the Prototype Core Team. They'll be in charge of maintaining Prototype, deciding what makes the cut for new releases, and handling day-to-day operations. + +This change in responsibility will let me focus on some infrastructural projects we need for the next-generation version of Prototype. It'll also help us fix bugs faster and release new versions more frequently. And I'll remain on the Core Team, contributing code and offering input on API design. + +Andrew and Tobie have proved themselves to be worthy keepers of the code, so I'm certain Prototype is in good hands. Congratulations, guys, and thanks for all your hard work! + diff --git a/_posts/2009-09-01-prototype-1-6-1-released.markdown b/_posts/2009-09-01-prototype-1-6-1-released.markdown new file mode 100644 index 000000000..9460b754a --- /dev/null +++ b/_posts/2009-09-01-prototype-1-6-1-released.markdown @@ -0,0 +1,39 @@ +--- +layout: blog_archive +author: Sam Stephenson +author_url: http://conio.net/ +sections: Featured, Releases, blog +title: "Prototype 1.6.1 released" +--- + +We're pleased to announce the release of Prototype 1.6.1 today. This version features improved performance, an element metadata storage system, new mouse events, and compatibility with the latest browsers. It's also the first release of Prototype built with [Sprockets](http://getsprockets.org/), our JavaScript packaging tool, and [PDoc](http://pdoc.org/), our inline documentation tool. + +### Highlights + +* **Full compatibility with new browsers.** This version of Prototype fully supports versions 1.0 and higher of Google Chrome, and Internet Explorer 8 in both compatibility mode and super-standards mode. + +* **Element metadata storage.** Easily associate JavaScript key/value pairs with a DOM element. [See the blog post that started it off.](http://prototypejs.org/2009/2/16/pimp-my-code-1-element-storage) + +* **New mouse events.** Internet Explorer's proprietary "mouseenter" and "mouseleave" events are now available in all browsers. + +* **Improved performance and housekeeping.** The frequently used Function#bind, String#escapeHTML, and Element#down methods are faster, and Prototype is better at cleaning up after itself. + +* **Built with Sprockets.** You can now include the Prototype source code repository in your application and use [Sprockets](http://getsprockets.org/) for dependency management and distribution. + +* **Inline documentation with PDoc.** Our [API documentation](http://api.prototypejs.org/) is now stored in the source code with [PDoc](http://pdoc.org/) so it's easy to send patches or view documentation for a specific version. + +See the [RC2 blog post](http://prototypejs.org/2009/3/27/prototype-1-6-1-rc2-ie8-compatibility-element-storage-and-bug-fixes), [RC3 blog post](http://prototypejs.org/2009/6/16/prototype-1-6-1-rc3-chrome-support-and-pdoc), and [CHANGELOG](http://github.com/sstephenson/prototype/blob/f405b2c510e09b55d08c926a9e1a5c2e2d0a1834/CHANGELOG) for more details. + + +### Download, report bugs, and get help + +* [Download Prototype 1.6.1](http://prototypejs.org/assets/2009/8/31/prototype.js) +* [View the API documentation](http://api.prototypejs.org/) +* [Check out the Prototype source code](http://github.com/sstephenson/prototype/) on GitHub +* [Submit bug reports](http://prototype.lighthouseapp.com/) to Lighthouse +* [Get Prototype help](http://prototypejs.org/discuss) on the mailing list or #prototype IRC channel +* [Interact with the Core Team](http://groups.google.com/group/prototype-core) on the protoype-core mailing list + + +We hope you enjoy the new version! + diff --git a/assets/2007/1/11/apple.gif b/assets/2007/1/11/apple.gif new file mode 100644 index 000000000..fd39e80c0 Binary files /dev/null and b/assets/2007/1/11/apple.gif differ diff --git a/assets/2007/1/11/apple_thumb.gif b/assets/2007/1/11/apple_thumb.gif new file mode 100644 index 000000000..a76397b2a Binary files /dev/null and b/assets/2007/1/11/apple_thumb.gif differ diff --git a/assets/2007/1/11/apple_tiny.gif b/assets/2007/1/11/apple_tiny.gif new file mode 100644 index 000000000..c937b0199 Binary files /dev/null and b/assets/2007/1/11/apple_tiny.gif differ diff --git a/assets/2007/1/11/blinksale.gif b/assets/2007/1/11/blinksale.gif new file mode 100644 index 000000000..d72e30525 Binary files /dev/null and b/assets/2007/1/11/blinksale.gif differ diff --git a/assets/2007/1/11/blinksale_thumb.gif b/assets/2007/1/11/blinksale_thumb.gif new file mode 100644 index 000000000..bfb141fc3 Binary files /dev/null and b/assets/2007/1/11/blinksale_thumb.gif differ diff --git a/assets/2007/1/11/blinksale_tiny.gif b/assets/2007/1/11/blinksale_tiny.gif new file mode 100644 index 000000000..4f4bb1107 Binary files /dev/null and b/assets/2007/1/11/blinksale_tiny.gif differ diff --git a/assets/2007/1/11/digg_1.gif b/assets/2007/1/11/digg_1.gif new file mode 100644 index 000000000..c8090d18c Binary files /dev/null and b/assets/2007/1/11/digg_1.gif differ diff --git a/assets/2007/1/11/digg_1_thumb.gif b/assets/2007/1/11/digg_1_thumb.gif new file mode 100644 index 000000000..e973cdaee Binary files /dev/null and b/assets/2007/1/11/digg_1_thumb.gif differ diff --git a/assets/2007/1/11/digg_1_tiny.gif b/assets/2007/1/11/digg_1_tiny.gif new file mode 100644 index 000000000..222f77a9a Binary files /dev/null and b/assets/2007/1/11/digg_1_tiny.gif differ diff --git a/assets/2007/1/11/nbc.gif b/assets/2007/1/11/nbc.gif new file mode 100644 index 000000000..676024ad4 Binary files /dev/null and b/assets/2007/1/11/nbc.gif differ diff --git a/assets/2007/1/11/nbc_thumb.gif b/assets/2007/1/11/nbc_thumb.gif new file mode 100644 index 000000000..ce2508f72 Binary files /dev/null and b/assets/2007/1/11/nbc_thumb.gif differ diff --git a/assets/2007/1/11/nbc_tiny.gif b/assets/2007/1/11/nbc_tiny.gif new file mode 100644 index 000000000..57d00cafe Binary files /dev/null and b/assets/2007/1/11/nbc_tiny.gif differ diff --git a/assets/2007/1/11/tivo.gif b/assets/2007/1/11/tivo.gif new file mode 100644 index 000000000..cc9ac3397 Binary files /dev/null and b/assets/2007/1/11/tivo.gif differ diff --git a/assets/2007/1/11/tivo_thumb.gif b/assets/2007/1/11/tivo_thumb.gif new file mode 100644 index 000000000..2aec7af5f Binary files /dev/null and b/assets/2007/1/11/tivo_thumb.gif differ diff --git a/assets/2007/1/11/tivo_tiny.gif b/assets/2007/1/11/tivo_tiny.gif new file mode 100644 index 000000000..3dd5c8504 Binary files /dev/null and b/assets/2007/1/11/tivo_tiny.gif differ diff --git a/assets/2007/1/14/chairs.jpg b/assets/2007/1/14/chairs.jpg new file mode 100644 index 000000000..450b48249 Binary files /dev/null and b/assets/2007/1/14/chairs.jpg differ diff --git a/assets/2007/1/14/chairs_thumb.jpg b/assets/2007/1/14/chairs_thumb.jpg new file mode 100644 index 000000000..11484945d Binary files /dev/null and b/assets/2007/1/14/chairs_thumb.jpg differ diff --git a/assets/2007/1/14/chairs_tiny.jpg b/assets/2007/1/14/chairs_tiny.jpg new file mode 100644 index 000000000..43d213d14 Binary files /dev/null and b/assets/2007/1/14/chairs_tiny.jpg differ diff --git a/assets/2007/1/14/prototype.png b/assets/2007/1/14/prototype.png new file mode 100644 index 000000000..1cddc239b Binary files /dev/null and b/assets/2007/1/14/prototype.png differ diff --git a/assets/2007/1/14/prototype_thumb.png b/assets/2007/1/14/prototype_thumb.png new file mode 100644 index 000000000..fa055a3fb Binary files /dev/null and b/assets/2007/1/14/prototype_thumb.png differ diff --git a/assets/2007/1/14/prototype_tiny.png b/assets/2007/1/14/prototype_tiny.png new file mode 100644 index 000000000..cf7a1a7fa Binary files /dev/null and b/assets/2007/1/14/prototype_tiny.png differ diff --git a/assets/2007/1/15/array-assertions-light.png b/assets/2007/1/15/array-assertions-light.png new file mode 100644 index 000000000..849e81bdf Binary files /dev/null and b/assets/2007/1/15/array-assertions-light.png differ diff --git a/assets/2007/1/15/array-assertions-light_thumb.png b/assets/2007/1/15/array-assertions-light_thumb.png new file mode 100644 index 000000000..1340856a4 Binary files /dev/null and b/assets/2007/1/15/array-assertions-light_thumb.png differ diff --git a/assets/2007/1/15/array-assertions-light_tiny.png b/assets/2007/1/15/array-assertions-light_tiny.png new file mode 100644 index 000000000..3e1788686 Binary files /dev/null and b/assets/2007/1/15/array-assertions-light_tiny.png differ diff --git a/assets/2007/1/15/array-assertions.png b/assets/2007/1/15/array-assertions.png new file mode 100644 index 000000000..50bf592a9 Binary files /dev/null and b/assets/2007/1/15/array-assertions.png differ diff --git a/assets/2007/1/15/array-assertions_thumb.png b/assets/2007/1/15/array-assertions_thumb.png new file mode 100644 index 000000000..c7c7c57c2 Binary files /dev/null and b/assets/2007/1/15/array-assertions_thumb.png differ diff --git a/assets/2007/1/15/array-assertions_tiny.png b/assets/2007/1/15/array-assertions_tiny.png new file mode 100644 index 000000000..0cd5040a6 Binary files /dev/null and b/assets/2007/1/15/array-assertions_tiny.png differ diff --git a/assets/2007/1/15/array-fail.png b/assets/2007/1/15/array-fail.png new file mode 100644 index 000000000..a2460f456 Binary files /dev/null and b/assets/2007/1/15/array-fail.png differ diff --git a/assets/2007/1/15/array-fail_thumb.png b/assets/2007/1/15/array-fail_thumb.png new file mode 100644 index 000000000..8fc1ceca6 Binary files /dev/null and b/assets/2007/1/15/array-fail_thumb.png differ diff --git a/assets/2007/1/15/array-fail_tiny.png b/assets/2007/1/15/array-fail_tiny.png new file mode 100644 index 000000000..e2625279c Binary files /dev/null and b/assets/2007/1/15/array-fail_tiny.png differ diff --git a/assets/2007/1/15/makepos_after.png b/assets/2007/1/15/makepos_after.png new file mode 100644 index 000000000..8cd1d3249 Binary files /dev/null and b/assets/2007/1/15/makepos_after.png differ diff --git a/assets/2007/1/15/makepos_after_thumb.png b/assets/2007/1/15/makepos_after_thumb.png new file mode 100644 index 000000000..7cbbacc7d Binary files /dev/null and b/assets/2007/1/15/makepos_after_thumb.png differ diff --git a/assets/2007/1/15/makepos_after_tiny.png b/assets/2007/1/15/makepos_after_tiny.png new file mode 100644 index 000000000..c59f45254 Binary files /dev/null and b/assets/2007/1/15/makepos_after_tiny.png differ diff --git a/assets/2007/1/15/makepos_before.png b/assets/2007/1/15/makepos_before.png new file mode 100644 index 000000000..6bbfd85a1 Binary files /dev/null and b/assets/2007/1/15/makepos_before.png differ diff --git a/assets/2007/1/15/makepos_before_thumb.png b/assets/2007/1/15/makepos_before_thumb.png new file mode 100644 index 000000000..f70a00eac Binary files /dev/null and b/assets/2007/1/15/makepos_before_thumb.png differ diff --git a/assets/2007/1/15/makepos_before_tiny.png b/assets/2007/1/15/makepos_before_tiny.png new file mode 100644 index 000000000..fe12df772 Binary files /dev/null and b/assets/2007/1/15/makepos_before_tiny.png differ diff --git a/assets/2007/1/18/TDD04.jpg b/assets/2007/1/18/TDD04.jpg new file mode 100644 index 000000000..e55f23eef Binary files /dev/null and b/assets/2007/1/18/TDD04.jpg differ diff --git a/assets/2007/1/18/TDD04_thumb.jpg b/assets/2007/1/18/TDD04_thumb.jpg new file mode 100644 index 000000000..3cbed5acc Binary files /dev/null and b/assets/2007/1/18/TDD04_thumb.jpg differ diff --git a/assets/2007/1/18/TDD04_tiny.jpg b/assets/2007/1/18/TDD04_tiny.jpg new file mode 100644 index 000000000..157c95c46 Binary files /dev/null and b/assets/2007/1/18/TDD04_tiny.jpg differ diff --git a/assets/2007/1/18/headshot_prototype.jpg b/assets/2007/1/18/headshot_prototype.jpg new file mode 100644 index 000000000..e88ff0a2e Binary files /dev/null and b/assets/2007/1/18/headshot_prototype.jpg differ diff --git a/assets/2007/1/18/headshot_prototype_thumb.jpg b/assets/2007/1/18/headshot_prototype_thumb.jpg new file mode 100644 index 000000000..824d31985 Binary files /dev/null and b/assets/2007/1/18/headshot_prototype_thumb.jpg differ diff --git a/assets/2007/1/18/headshot_prototype_tiny.jpg b/assets/2007/1/18/headshot_prototype_tiny.jpg new file mode 100644 index 000000000..8f3303fae Binary files /dev/null and b/assets/2007/1/18/headshot_prototype_tiny.jpg differ diff --git a/assets/2007/1/18/justin.jpg b/assets/2007/1/18/justin.jpg new file mode 100644 index 000000000..613cfe221 Binary files /dev/null and b/assets/2007/1/18/justin.jpg differ diff --git a/assets/2007/1/18/justin_thumb.jpg b/assets/2007/1/18/justin_thumb.jpg new file mode 100644 index 000000000..ceb7f3f91 Binary files /dev/null and b/assets/2007/1/18/justin_thumb.jpg differ diff --git a/assets/2007/1/18/justin_tiny.jpg b/assets/2007/1/18/justin_tiny.jpg new file mode 100644 index 000000000..908094f06 Binary files /dev/null and b/assets/2007/1/18/justin_tiny.jpg differ diff --git a/assets/2007/1/18/mislav.jpg b/assets/2007/1/18/mislav.jpg new file mode 100644 index 000000000..9959171ab Binary files /dev/null and b/assets/2007/1/18/mislav.jpg differ diff --git a/assets/2007/1/18/mislav_thumb.jpg b/assets/2007/1/18/mislav_thumb.jpg new file mode 100644 index 000000000..0110b6c8d Binary files /dev/null and b/assets/2007/1/18/mislav_thumb.jpg differ diff --git a/assets/2007/1/18/mislav_tiny.jpg b/assets/2007/1/18/mislav_tiny.jpg new file mode 100644 index 000000000..020c04a4e Binary files /dev/null and b/assets/2007/1/18/mislav_tiny.jpg differ diff --git a/assets/2007/1/18/prototype.js b/assets/2007/1/18/prototype.js new file mode 100644 index 000000000..505822177 --- /dev/null +++ b/assets/2007/1/18/prototype.js @@ -0,0 +1,2515 @@ +/* Prototype JavaScript framework, version 1.5.0 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://prototype.conio.net/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.0', + BrowserFeatures: { + XPath: !!document.evaluate + }, + + ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', + emptyFunction: function() {}, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + var digits = this.toString(16); + if (this < 16) return '0' + digits; + return digits; + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + } +}); + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +String.interpret = function(value){ + return value == null ? '' : String(value); +} + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var div = document.createElement('div'); + var text = document.createTextNode(this); + div.appendChild(text); + return div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('',function(memo,node){ return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var name = decodeURIComponent(pair[0]); + var value = pair[1] ? decodeURIComponent(pair[1]) : undefined; + + if (hash[name] !== undefined) { + if (hash[name].constructor != Array) + hash[name] = [hash[name]]; + if (value) hash[name].push(value); + } + else hash[name] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function(){ + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.replace(/\\/g, '\\\\'); + if (useDoubleQuotes) + return '"' + escapedString.replace(/"/g, '\\"') + '"'; + else + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = new Object(); +var $continue = new Object(); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + try { + iterator(value, index++); + } catch (e) { + if (e != $continue) throw e; + } + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function() { + return this.inject([], function(array, value) { + return array.include(value) ? array : array.concat([value]); + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string){ + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if(window.opera){ + Array.prototype.concat = function(){ + var array = []; + for(var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for(var i = 0, length = arguments.length; i < length; i++) { + if(arguments[i].constructor == Array) { + for(var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(obj) { + Object.extend(this, obj || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + + if (pair.value && pair.value.constructor == Array) { + var values = pair.value.compact(); + if (values.length < 2) pair.value = values.reduce(); + else { + key = encodeURIComponent(pair.key); + values.each(function(value) { + value = value != undefined ? encodeURIComponent(value) : ''; + parts.push(key + '=' + encodeURIComponent(value)); + }); + return; + } + } + if (pair.value == undefined) pair[1] = ''; + parts.push(pair.map(encodeURIComponent).join('=')); + }); + + return parts.join('&'); + } +}); + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + } +}); + +function $H(object) { + if (object && object.constructor == Hash) return object; + return new Hash(object); +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = this.options.parameters; + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + params = Hash.toQueryString(params); + if (params && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) params += '&_=' + + // when GET, append parameters to URL + if (this.method == 'get' && params) + this.url += (this.url.indexOf('?') > -1 ? '&' : '?') + params; + + try { + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + var body = this.method == 'post' ? (this.options.postBody || params) : null; + + this.transport.send(body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + if ((this.getHeader('Content-type') || 'text/javascript').strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? eval('(' + json + ')') : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval(this.transport.responseText); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +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); +} + +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) { + if (Prototype.BrowserFeatures.XPath) { + var q = ".//*[contains(concat(' ', @class, ' '), ' " + className + " ')]"; + return document._getElementsByXPath(q, parentElement); + } else { + var children = ($(parentElement) || document.body).getElementsByTagName('*'); + var elements = [], child; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) + var Element = new Object(); + +Element.extend = function(element) { + if (!element || _nativeExtensions || element.nodeType == 3) return element; + + if (!element._extended && element.tagName && element != window) { + var methods = Object.clone(Element.Methods), cache = Element.extend.cache; + + if (element.tagName == 'FORM') + Object.extend(methods, Form.Methods); + if (['INPUT', 'TEXTAREA', 'SELECT'].include(element.tagName)) + Object.extend(methods, Form.Element.Methods); + + Object.extend(methods, Element.Methods.Simulated); + + for (var property in methods) { + var value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = cache.findOrStore(value); + } + } + + element._extended = true; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +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(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + 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) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + 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) { + return Selector.findElement($(element).ancestors(), expression, index); + }, + + down: function(element, expression, index) { + return Selector.findElement($(element).descendants(), expression, index); + }, + + previous: function(element, expression, index) { + return Selector.findElement($(element).previousSiblings(), expression, index); + }, + + next: function(element, expression, index) { + return Selector.findElement($(element).nextSiblings(), expression, index); + }, + + getElementsBySelector: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + getElementsByClassName: function(element, className) { + return document.getElementsByClassName(className, element); + }, + + readAttribute: function(element, name) { + element = $(element); + if (document.all && !window.opera) { + 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]; + if(attribute) return attribute.nodeValue; + } + 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); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.match(/^\s*$/); + }, + + 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); + if (['float','cssFloat'].include(style)) + style = (typeof element.style.styleFloat != 'undefined' ? 'styleFloat' : 'cssFloat'); + style = style.camelize(); + var value = element.style[style]; + if (!value) { + if (document.defaultView && document.defaultView.getComputedStyle) { + var css = document.defaultView.getComputedStyle(element, null); + value = css ? css[style] : null; + } else if (element.currentStyle) { + value = element.currentStyle[style]; + } + } + + if((value == 'auto') && ['width','height'].include(style) && (element.getStyle('display') != 'none')) + value = element['offset'+style.capitalize()] + 'px'; + + if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) + if (Element.getStyle(element, 'position') == 'static') value = 'auto'; + if(style == 'opacity') { + if(value) return parseFloat(value); + if(value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/)) + if(value[1]) return parseFloat(value[1]) / 100; + return 1.0; + } + return value == 'auto' ? null : value; + }, + + setStyle: function(element, style) { + element = $(element); + for (var name in style) { + var value = style[name]; + if(name == 'opacity') { + if (value == 1) { + value = (/Gecko/.test(navigator.userAgent) && + !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 0.999999 : 1.0; + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); + } else if(value == '') { + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,''); + } else { + if(value < 0.00001) value = 0; + if(/MSIE/.test(navigator.userAgent) && !window.opera) + element.style.filter = element.getStyle('filter').replace(/alpha\([^\)]*\)/gi,'') + + 'alpha(opacity='+value*100+')'; + } + } else if(['float','cssFloat'].include(name)) name = (typeof element.style.styleFloat != 'undefined') ? 'styleFloat' : 'cssFloat'; + element.style[name.camelize()] = value; + } + return element; + }, + + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + 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); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + 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; + }, + + 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}); + +Element._attributeTranslations = {}; + +Element._attributeTranslations.names = { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" +}; + +Element._attributeTranslations.values = { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } +}; + +Object.extend(Element._attributeTranslations.values, { + href: Element._attributeTranslations.values._getAttr, + src: Element._attributeTranslations.values._getAttr, + disabled: Element._attributeTranslations.values._flag, + checked: Element._attributeTranslations.values._flag, + readonly: Element._attributeTranslations.values._flag, + multiple: Element._attributeTranslations.values._flag +}); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations; + attribute = t.names[attribute] || attribute; + return $(element).getAttributeNode(attribute).specified; + } +}; + +// IE is missing .innerHTML support for TABLE-related elements +if (document.all && !window.opera){ + 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 = '' + html.stripScripts() + '
'; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 3; + break; + case 'TD': + div.innerHTML = '
' + html.stripScripts() + '
'; + 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; + } +}; + +Object.extend(Element, Element.Methods); + +var _nativeExtensions = false; + +if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + ['', 'Form', 'Input', 'TextArea', 'Select'].each(function(tag) { + var className = 'HTML' + tag + 'Element'; + if(window[className]) return; + var klass = window[className] = {}; + klass.prototype = document.createElement(tag ? tag.toLowerCase() : 'div').__proto__; + }); + +Element.addMethods = function(methods) { + Object.extend(Element.Methods, 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); + } + } + + if (typeof HTMLElement != 'undefined') { + copy(Element.Methods, HTMLElement.prototype); + copy(Element.Methods.Simulated, HTMLElement.prototype, true); + copy(Form.Methods, HTMLFormElement.prototype); + [HTMLInputElement, HTMLTextAreaElement, HTMLSelectElement].each(function(klass) { + copy(Form.Element.Methods, klass.prototype); + }); + _nativeExtensions = true; + } +} + +var Toggle = new Object(); +Toggle.display = Element.toggle; + +/*--------------------------------------------------------------------------*/ + +Abstract.Insertion = function(adjacency) { + this.adjacency = adjacency; +} + +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(); + 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); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + 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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +var Selector = Class.create(); +Selector.prototype = { + initialize: function(expression) { + this.params = {classNames: []}; + this.expression = expression.toString().strip(); + this.parseExpression(); + this.compileMatcher(); + }, + + parseExpression: function() { + function abort(message) { throw 'Parse error in selector: ' + message; } + + if (this.expression == '') abort('empty expression'); + + var params = this.params, expr = this.expression, match, modifier, clause, rest; + while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) { + params.attributes = params.attributes || []; + params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''}); + expr = match[1]; + } + + if (expr == '*') return this.params.wildcard = true; + + while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+)(.*)/i)) { + modifier = match[1], clause = match[2], rest = match[3]; + switch (modifier) { + case '#': params.id = clause; break; + case '.': params.classNames.push(clause); break; + case '': + case undefined: params.tagName = clause.toUpperCase(); break; + default: abort(expr.inspect()); + } + expr = rest; + } + + if (expr.length > 0) abort(expr.inspect()); + }, + + buildMatchExpression: function() { + var params = this.params, conditions = [], clause; + + if (params.wildcard) + conditions.push('true'); + if (clause = params.id) + conditions.push('element.readAttribute("id") == ' + clause.inspect()); + if (clause = params.tagName) + conditions.push('element.tagName.toUpperCase() == ' + clause.inspect()); + if ((clause = params.classNames).length > 0) + for (var i = 0, length = clause.length; i < length; i++) + conditions.push('element.hasClassName(' + clause[i].inspect() + ')'); + if (clause = params.attributes) { + clause.each(function(attribute) { + var value = 'element.readAttribute(' + attribute.name.inspect() + ')'; + var splitValueBy = function(delimiter) { + return value + ' && ' + value + '.split(' + delimiter.inspect() + ')'; + } + + switch (attribute.operator) { + case '=': conditions.push(value + ' == ' + attribute.value.inspect()); break; + case '~=': conditions.push(splitValueBy(' ') + '.include(' + attribute.value.inspect() + ')'); break; + case '|=': conditions.push( + splitValueBy('-') + '.first().toUpperCase() == ' + attribute.value.toUpperCase().inspect() + ); break; + case '!=': conditions.push(value + ' != ' + attribute.value.inspect()); break; + case '': + case undefined: conditions.push('element.hasAttribute(' + attribute.name.inspect() + ')'); break; + default: throw 'Unknown operator ' + attribute.operator + ' in selector'; + } + }); + } + + return conditions.join(' && '); + }, + + compileMatcher: function() { + this.match = new Function('element', 'if (!element.tagName) return false; \ + element = $(element); \ + return ' + this.buildMatchExpression()); + }, + + findElements: function(scope) { + var element; + + if (element = $(this.params.id)) + if (this.match(element)) + if (!scope || Element.childOf(element, scope)) + return [element]; + + scope = (scope || document).getElementsByTagName(this.params.tagName || '*'); + + var results = []; + for (var i = 0, length = scope.length; i < length; i++) + if (this.match(element = scope[i])) + results.push(Element.extend(element)); + + return results; + }, + + toString: function() { + return this.expression; + } +} + +Object.extend(Selector, { + matchElements: function(elements, expression) { + var selector = new Selector(expression); + return elements.select(selector.match.bind(selector)).map(Element.extend); + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') index = expression, expression = false; + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + return expressions.map(function(expression) { + return expression.match(/[^\s"]+(?:"[^"]*"[^\s"]+)*/g).inject([null], function(results, expr) { + var selector = new Selector(expr); + return results.inject([], function(elements, result) { + return elements.concat(selector.findElements(result || element)); + }); + }); + }).flatten(); + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != undefined) { + if (result[key]) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + form.getElements().each(function(element) { + element.blur(); + element.disabled = 'true'; + }); + return form; + }, + + enable: function(form) { + form = $(form); + form.getElements().each(function(element) { + element.disabled = ''; + }); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + } +} + +Object.extend(Form, Form.Methods); + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + element.focus(); + if (element.select && ( element.tagName.toLowerCase() != 'input' || + !['button', 'reset', 'submit'].include(element.type) ) ) + element.select(); + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.blur(); + element.disabled = false; + return element; + } +} + +Object.extend(Form.Element, Form.Element.Methods); +var Field = Form.Element; +var $F = Form.Element.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return event.target || event.srcElement; + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (navigator.appVersion.match(/Konqueror|Safari|KHTML/) + || element.detachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (navigator.appVersion.match(/\bMSIE\b/)) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent==document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/assets/2007/1/18/sam.jpg b/assets/2007/1/18/sam.jpg new file mode 100644 index 000000000..45b088e1a Binary files /dev/null and b/assets/2007/1/18/sam.jpg differ diff --git a/assets/2007/1/18/sam_thumb.jpg b/assets/2007/1/18/sam_thumb.jpg new file mode 100644 index 000000000..7279cccbc Binary files /dev/null and b/assets/2007/1/18/sam_thumb.jpg differ diff --git a/assets/2007/1/18/sam_tiny.jpg b/assets/2007/1/18/sam_tiny.jpg new file mode 100644 index 000000000..25f9a33b8 Binary files /dev/null and b/assets/2007/1/18/sam_tiny.jpg differ diff --git a/assets/2007/1/18/sco.jpg b/assets/2007/1/18/sco.jpg new file mode 100644 index 000000000..64f2b2da4 Binary files /dev/null and b/assets/2007/1/18/sco.jpg differ diff --git a/assets/2007/1/18/sco_thumb.jpg b/assets/2007/1/18/sco_thumb.jpg new file mode 100644 index 000000000..dc89875bd Binary files /dev/null and b/assets/2007/1/18/sco_thumb.jpg differ diff --git a/assets/2007/1/18/sco_tiny.jpg b/assets/2007/1/18/sco_tiny.jpg new file mode 100644 index 000000000..004065581 Binary files /dev/null and b/assets/2007/1/18/sco_tiny.jpg differ diff --git a/assets/2007/1/18/thomas_fuchs.jpg b/assets/2007/1/18/thomas_fuchs.jpg new file mode 100644 index 000000000..a12338bb2 Binary files /dev/null and b/assets/2007/1/18/thomas_fuchs.jpg differ diff --git a/assets/2007/1/18/thomas_fuchs_thumb.jpg b/assets/2007/1/18/thomas_fuchs_thumb.jpg new file mode 100644 index 000000000..579d672db Binary files /dev/null and b/assets/2007/1/18/thomas_fuchs_thumb.jpg differ diff --git a/assets/2007/1/18/thomas_fuchs_tiny.jpg b/assets/2007/1/18/thomas_fuchs_tiny.jpg new file mode 100644 index 000000000..740a64751 Binary files /dev/null and b/assets/2007/1/18/thomas_fuchs_tiny.jpg differ diff --git a/assets/2007/1/19/tobie.jpg b/assets/2007/1/19/tobie.jpg new file mode 100644 index 000000000..a682a8525 Binary files /dev/null and b/assets/2007/1/19/tobie.jpg differ diff --git a/assets/2007/1/19/tobie_thumb.jpg b/assets/2007/1/19/tobie_thumb.jpg new file mode 100644 index 000000000..bc80a8b6b Binary files /dev/null and b/assets/2007/1/19/tobie_thumb.jpg differ diff --git a/assets/2007/1/19/tobie_tiny.jpg b/assets/2007/1/19/tobie_tiny.jpg new file mode 100644 index 000000000..0e637d2b7 Binary files /dev/null and b/assets/2007/1/19/tobie_tiny.jpg differ diff --git a/assets/2007/1/19/wollzelle.gif b/assets/2007/1/19/wollzelle.gif new file mode 100644 index 000000000..049ffd90d Binary files /dev/null and b/assets/2007/1/19/wollzelle.gif differ diff --git a/assets/2007/1/19/wollzelle_thumb.gif b/assets/2007/1/19/wollzelle_thumb.gif new file mode 100644 index 000000000..f62704841 Binary files /dev/null and b/assets/2007/1/19/wollzelle_thumb.gif differ diff --git a/assets/2007/1/19/wollzelle_tiny.gif b/assets/2007/1/19/wollzelle_tiny.gif new file mode 100644 index 000000000..16ca306fa Binary files /dev/null and b/assets/2007/1/19/wollzelle_tiny.gif differ diff --git a/assets/2007/1/20/backpack.gif b/assets/2007/1/20/backpack.gif new file mode 100644 index 000000000..dc323fd6b Binary files /dev/null and b/assets/2007/1/20/backpack.gif differ diff --git a/assets/2007/1/20/backpack_thumb.gif b/assets/2007/1/20/backpack_thumb.gif new file mode 100644 index 000000000..a458c0058 Binary files /dev/null and b/assets/2007/1/20/backpack_thumb.gif differ diff --git a/assets/2007/1/20/backpack_tiny.gif b/assets/2007/1/20/backpack_tiny.gif new file mode 100644 index 000000000..6ef3c83f2 Binary files /dev/null and b/assets/2007/1/20/backpack_tiny.gif differ diff --git a/assets/2007/1/20/basecamp.gif b/assets/2007/1/20/basecamp.gif new file mode 100644 index 000000000..d285069f4 Binary files /dev/null and b/assets/2007/1/20/basecamp.gif differ diff --git a/assets/2007/1/20/basecamp_thumb.gif b/assets/2007/1/20/basecamp_thumb.gif new file mode 100644 index 000000000..097266ad8 Binary files /dev/null and b/assets/2007/1/20/basecamp_thumb.gif differ diff --git a/assets/2007/1/20/basecamp_tiny.gif b/assets/2007/1/20/basecamp_tiny.gif new file mode 100644 index 000000000..ef5041340 Binary files /dev/null and b/assets/2007/1/20/basecamp_tiny.gif differ diff --git a/assets/2007/1/20/campfire.gif b/assets/2007/1/20/campfire.gif new file mode 100644 index 000000000..19a980a2f Binary files /dev/null and b/assets/2007/1/20/campfire.gif differ diff --git a/assets/2007/1/20/campfire_thumb.gif b/assets/2007/1/20/campfire_thumb.gif new file mode 100644 index 000000000..887918c19 Binary files /dev/null and b/assets/2007/1/20/campfire_thumb.gif differ diff --git a/assets/2007/1/20/campfire_tiny.gif b/assets/2007/1/20/campfire_tiny.gif new file mode 100644 index 000000000..34fe421e2 Binary files /dev/null and b/assets/2007/1/20/campfire_tiny.gif differ diff --git a/assets/2007/1/20/shopify-only-88x31.png b/assets/2007/1/20/shopify-only-88x31.png new file mode 100644 index 000000000..4ac958e1a Binary files /dev/null and b/assets/2007/1/20/shopify-only-88x31.png differ diff --git a/assets/2007/1/20/shopify-only-88x31_thumb.png b/assets/2007/1/20/shopify-only-88x31_thumb.png new file mode 100644 index 000000000..cdfbdc1ba Binary files /dev/null and b/assets/2007/1/20/shopify-only-88x31_thumb.png differ diff --git a/assets/2007/1/20/shopify-only-88x31_tiny.png b/assets/2007/1/20/shopify-only-88x31_tiny.png new file mode 100644 index 000000000..9a61c5184 Binary files /dev/null and b/assets/2007/1/20/shopify-only-88x31_tiny.png differ diff --git a/assets/2007/1/20/shopify.gif b/assets/2007/1/20/shopify.gif new file mode 100644 index 000000000..4a2b162d2 Binary files /dev/null and b/assets/2007/1/20/shopify.gif differ diff --git a/assets/2007/1/20/shopify_thumb.gif b/assets/2007/1/20/shopify_thumb.gif new file mode 100644 index 000000000..a334964d9 Binary files /dev/null and b/assets/2007/1/20/shopify_thumb.gif differ diff --git a/assets/2007/1/20/shopify_tiny.gif b/assets/2007/1/20/shopify_tiny.gif new file mode 100644 index 000000000..7c7a7f074 Binary files /dev/null and b/assets/2007/1/20/shopify_tiny.gif differ diff --git a/assets/2007/1/24/espn.gif b/assets/2007/1/24/espn.gif new file mode 100644 index 000000000..4648f6710 Binary files /dev/null and b/assets/2007/1/24/espn.gif differ diff --git a/assets/2007/1/24/espn_thumb.gif b/assets/2007/1/24/espn_thumb.gif new file mode 100644 index 000000000..2ba7065b4 Binary files /dev/null and b/assets/2007/1/24/espn_thumb.gif differ diff --git a/assets/2007/1/24/espn_tiny.gif b/assets/2007/1/24/espn_tiny.gif new file mode 100644 index 000000000..fe286d05f Binary files /dev/null and b/assets/2007/1/24/espn_tiny.gif differ diff --git a/assets/2007/1/31/pcore.jpg b/assets/2007/1/31/pcore.jpg new file mode 100644 index 000000000..1be88428c Binary files /dev/null and b/assets/2007/1/31/pcore.jpg differ diff --git a/assets/2007/1/31/pcore_thumb.jpg b/assets/2007/1/31/pcore_thumb.jpg new file mode 100644 index 000000000..05ec87362 Binary files /dev/null and b/assets/2007/1/31/pcore_thumb.jpg differ diff --git a/assets/2007/1/31/pcore_tiny.jpg b/assets/2007/1/31/pcore_tiny.jpg new file mode 100644 index 000000000..dcce436d9 Binary files /dev/null and b/assets/2007/1/31/pcore_tiny.jpg differ diff --git a/assets/2007/10/10/logo.gif b/assets/2007/10/10/logo.gif new file mode 100644 index 000000000..346cec2ec Binary files /dev/null and b/assets/2007/10/10/logo.gif differ diff --git a/assets/2007/10/10/logo_thumb.gif b/assets/2007/10/10/logo_thumb.gif new file mode 100644 index 000000000..75202e877 Binary files /dev/null and b/assets/2007/10/10/logo_thumb.gif differ diff --git a/assets/2007/10/10/logo_tiny.gif b/assets/2007/10/10/logo_tiny.gif new file mode 100644 index 000000000..88061f6cc Binary files /dev/null and b/assets/2007/10/10/logo_tiny.gif differ diff --git a/assets/2007/10/11/prototype-dev-7839.js b/assets/2007/10/11/prototype-dev-7839.js new file mode 100644 index 000000000..dc716af25 --- /dev/null +++ b/assets/2007/10/11/prototype-dev-7839.js @@ -0,0 +1,4140 @@ +/* Prototype JavaScript framework, version 1.6.0_rc1 development version [rev. 7839] + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.6.0_rc0', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, + MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/) + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + document.createElement('div').__proto__ !== + document.createElement('form').__proto__ + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + +/* Based on Alex Arnell's inheritance implementation. */ +var Class = { + create: function() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + var subclass = function() { }; + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + + return klass; + } +}; + +Class.Methods = { + addMethods: function(source) { + var ancestor = this.superclass && this.superclass.prototype; + + for (var property in source) { + var value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value, value = Object.extend((function(m) { + return function() { return ancestor[m].apply(this, arguments) }; + })(property).wrap(method), { + valueOf: function() { return method }, + toString: function() { return method.toString() } + }); + } + this.prototype[property] = value; + } + + return this; + } +}; + +var Abstract = { }; + +Object.extend = function(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; +}; + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (Object.isElement(object)) return; + + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + }, + + toHTML: function(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({ }, object); + }, + + isElement: function(object) { + return object && object.nodeType == 1; + }, + + isArray: function(object) { + return object && object.constructor === Array; + }, + + isFunction: function(object) { + return typeof object == "function"; + }, + + isString: function(object) { + return typeof object == "string"; + }, + + isNumber: function(object) { + return typeof object == "number"; + }, + + isUndefined: function(object) { + return typeof object == "undefined"; + } +}); + +Object.extend(Function.prototype, { + argumentNames: function() { + var names = this.toString().match(/^[\s\(]*function\s*\((.*?)\)/)[1].split(",").invoke("strip"); + return names.length == 1 && !names[0] ? [] : names; + }, + + bind: function() { + if (arguments.length < 2 && arguments[0] === undefined) return this; + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } + }, + + bindAsEventListener: function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } + }, + + curry: function() { + if (!arguments.length) return this; + var __method = this, args = $A(arguments); + return function() { + return __method.apply(this, args.concat($A(arguments))); + } + }, + + delay: function() { + var __method = this, args = $A(arguments), timeout = args.shift() * 1000; + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + }, + + wrap: function(wrapper) { + var __method = this; + return function() { + return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); + } + }, + + methodize: function() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + return __method.apply(null, [this].concat($A(arguments))); + }; + } +}); + +Function.prototype.defer = Function.prototype.delay.curry(0.01); + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + } finally { + this.currentlyExecuting = false; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = new Element('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + isJSON: function() { + var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + }, + + interpolate: function(object, pattern) { + return new Template(this, pattern).evaluate(object); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +}; + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return ''; + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); + if (match == null) return ''; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }.bind(this)); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = { + each: function(iterator, context) { + var index = 0; + iterator = iterator.bind(context); + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + }, + + all: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator(value, index)); + }); + return results; + }, + + detect: function(iterator, context) { + iterator = iterator.bind(context); + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator, context) { + iterator = iterator.bind(context); + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(filter, iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(filter); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator(value, index)); + }); + return results; + }, + + include: function(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator, context) { + iterator = iterator.bind(context); + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result; + this.each(function(value, index) { + value = iterator(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result; + this.each(function(value, index) { + value = iterator(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator, context) { + iterator = iterator.bind(context); + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator, context) { + iterator = iterator.bind(context); + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +}; + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + filter: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray, + every: Enumerable.all, + some: Enumerable.any +}); +function $A(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + function $A(iterable) { + if (!iterable) return []; + if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Array.from = $A; + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(Object.isArray(value) ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + intersect: function(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +// use native browser JS 1.6 implementation if available +if (Object.isFunction(Array.prototype.forEach)) + Array.prototype._each = Array.prototype.forEach; + +if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; +}; + +if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; +}; + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (Object.isArray(arguments[i])) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + }; +} +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +$w('abs round ceil floor').each(function(method){ + Number.prototype[method] = Math[method].methodize(); +}); +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || { }); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (Object.isArray(value)) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +}; + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + index: function(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (!Object.isArray(result)) result = [result]; + result.push(value); + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create({ + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + } +}); + +Object.extend(ObjectRange.prototype, Enumerable); + +ObjectRange.prototype.include = function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; +}; + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +}; + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); + +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + } +}); + +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this.getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = xml === undefined ? null : xml; + this.responseJSON = this.getResponseJSON(); + } + }, + + status: 0, + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + try { + return json ? json.evalJSON(this.request.options.sanitizeJSON) : null; + } catch (e) { + this.request.dispatchException(e); + } + }, + + getResponseJSON: function() { + var options = this.request.options; + try { + if (options.evalJSON == 'force' || (options.evalJSON && + (this.getHeader('Content-type') || '').include('application/json'))) + return this.transport.responseText.evalJSON(options.sanitizeJSON); + return null; + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = options || { }; + var onComplete = options.onComplete; + options.onComplete = (function(response, param) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, param); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + + if (this.success()) { + if (this.onComplete) this.onComplete.bind(this).defer(); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +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(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + // DOM level 2 ECMAScript Language Binding + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + +(function() { + var element = this.Element; + this.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (Prototype.Browser.IE && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(this.Element, element || { }); +}).call(window); + +Element.cache = { }; + +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, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + content = Object.toHTML(content); + element.innerHTML = content.stripScripts(); + content.evalScripts.bind(content).defer(); + return element; + }, + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, t, range; + + for (position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + t = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + t.insert(element, content); + continue; + } + + content = Object.toHTML(content); + + range = element.ownerDocument.createRange(); + t.initializeRange(element, range); + t.insert(element, range.createContextualFragment(content.stripScripts())); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + 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]; + }, + + select: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + adjacent: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = element.readAttribute('id'), self = arguments.callee; + if (id) return id; + do { id = 'anonymous_element_' + self.counter++ } while ($(id)); + element.writeAttribute('id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = value === undefined ? true : value; + + for (var attr in attributes) { + var name = t.names[attr] || attr, value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!element.hasClassName(className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return element[element.hasClassName(className) ? + 'removeClassName' : 'addClassName'](className); + }, + + // 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + 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 = element.cumulativeOffset(); + 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) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + 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); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + 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; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (element.getStyle('position') == 'absolute') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + var offsets = element.positionedOffset(); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (element.getStyle('position') == 'relative') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || element.tagName == 'BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + // find page position of source + source = $(source); + var p = source.viewportOffset(); + + // find coordinate system to use + element = $(element); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(element, 'position') == 'absolute') { + parent = element.getOffsetParent(); + delta = parent.viewportOffset(); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Element.Methods.identify.counter = 1; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + + +if (!document.createRange || Prototype.Browser.Opera) { + Element.Methods.insert = function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = { bottom: insertions }; + + var t = Element._insertionTranslations, content, position, pos, tagName; + + for (position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + pos = t[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + pos.insert(element, content); + continue; + } + + content = Object.toHTML(content); + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + if (t.tags[tagName]) { + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + if (position == 'top' || position == 'after') fragments.reverse(); + fragments.each(pos.insert.curry(element)); + } + else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); + + content.evalScripts.bind(content).defer(); + } + + return element; + }; +} + +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); + } + }; + Element.Methods._readAttribute = Element.Methods.readAttribute; + Element.Methods.readAttribute = function(element, attribute) { + if (attribute == 'title') return element.title; + return Element._readAttribute(element, attribute); + }; +} + +else if (Prototype.Browser.IE) { + $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + var position = element.getStyle('position'); + if (position != 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + 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) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + if (!element.currentStyle.hasLayout) element.style.zoom = 1; + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = { + read: { + names: { + 'class': 'className', + 'for': 'htmlFor' + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: function(element, attribute) { + var attribute = element.getAttribute(attribute); + return attribute ? attribute.toString().slice(23, -2) : null; + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + }; + + Element._attributeTranslations.write = { + names: Object.clone(Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr, + src: v._getAttr, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); +} + +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; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + // Safari returns margins on body which is incorrect if the child is absolutely + // positioned. For performance reasons, redefine Position.cumulativeOffset for + // KHTML/WebKit only. + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if (Prototype.Browser.IE || Prototype.Browser.Opera) { + // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements + Element.Methods.update = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + + content = Object.toHTML(content); + var tagName = element.tagName.toUpperCase(); + + if (tagName in Element._insertionTranslations.tags) { + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { element.appendChild(node) }); + } + else element.innerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +if (document.createElement('div').outerHTML) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: { + adjacency: 'beforeBegin', + insert: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + initializeRange: function(element, range) { + range.setStartBefore(element); + } + }, + top: { + adjacency: 'afterBegin', + insert: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + initializeRange: function(element, range) { + range.selectNodeContents(element); + range.collapse(true); + } + }, + bottom: { + adjacency: 'beforeEnd', + insert: function(element, node) { + element.appendChild(node); + } + }, + after: { + adjacency: 'afterEnd', + insert: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + initializeRange: function(element, range) { + range.setStartAfter(element); + } + }, + tags: { + TABLE: ['', '
', 1], + TBODY: ['', '
', 2], + TR: ['', '
', 3], + TD: ['
', '
', 4], + SELECT: ['', 1] + } +}; + +(function() { + this.bottom.initializeRange = this.top.initializeRange; + Object.extend(this.tags, { + THEAD: this.tags.TBODY, + TFOOT: this.tags.TBODY, + TH: this.tags.TD + }); +}).call(Element._insertionTranslations); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var 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.extend = (function() { + if (Prototype.BrowserFeatures.SpecificElementExtensions) + return Prototype.K; + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || element._extendedByPrototype || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName, property, value; + + // extend methods for specific tags + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + for (property in methods) { + value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + // extend methods for all tags (Safari doesn't need this) + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +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, { + "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 (Object.isArray(tagName)) 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; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + 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 (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + +document.viewport = { + getDimensions: function() { + var dimensions = { }; + $w('width height').each(function(d) { + var D = d.capitalize(); + dimensions[d] = self['inner' + D] || + (document.documentElement['client' + D] || document.body['client' + D]); + }); + return dimensions; + }, + + getWidth: function() { + return this.getDimensions().width; + }, + + getHeight: function() { + return this.getDimensions().height; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + this.tokens = []; + + var e = this.expression, ps = Selector.patterns, as = Selector.assertions; + var le, p, m; + + while (e && le !== e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + // use the Selector.assertions methods unless the selector + // is too complex. + if (as[i]) { + this.tokens.push([i, Object.clone(m)]); + e = e.replace(m[0], ''); + } else { + // reluctantly do a document-wide search + // and look for a match in the array + return this.findElements(document).include(element); + } + } + } + } + + var match = true, name, matches; + for (var i = 0, token; token = this.tokens[i]; i++) { + name = token[0], matches = token[1]; + if (!Selector.assertions[name](element, matches)) { + match = false; break; + } + } + + return match; + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}); + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + // for Selector.match and Element#match + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return Selector.operators[matches[2]](nodeValue, matches[3]); + } + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!targetNode) return []; + if (!nodes && root == document) return [targetNode]; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (options.hash === undefined) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + // a key is already present; construct an array of values + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + 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; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (value === undefined) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (value === undefined) return element.value; + else element.value = value; + }, + + select: function(element, index) { + if (index === undefined) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, value, single = !Object.isArray(index); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + value = this.optionValue(opt); + if (single) { + if (value == index) { + opt.selected = true; + return; + } + } + else opt.selected = index.include(value); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) var Event = { }; + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: { }, + + relatedTarget: function(event) { + var element; + switch(event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } +}); + +Event.Methods = { + element: function(event) { + var node = event.target; + return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); + }, + + findElement: function(event, expression) { + var element = Event.element(event); + return element.match(expression) ? element : element.up(expression); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointer: function(event) { + return { + x: event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)), + y: event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)) + }; + }, + + pointerX: function(event) { return Event.pointer(event).x }, + pointerY: function(event) { return Event.pointer(event).y }, + + stop: function(event) { + event.preventDefault(); + event.stopPropagation(); + } +}; + +Event.extend = (function() { + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return "[object Event]" } + }); + + return function(event) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + Object.extend(event, { + target: event.srcElement, + relatedTarget: Event.relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + return Object.extend(event, methods); + }; + + } else { + Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; + Object.extend(Event.prototype, methods); + return Prototype.K; + } +})(); + +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._eventID) return element._eventID; + arguments.callee.id = arguments.callee.id || 1; + return element._eventID = ++arguments.callee.id; + } + + function getDOMEventName(eventName) { + if (eventName && eventName.match(/:/)) return "dataavailable"; + return { keypress: "keydown" }[eventName] || eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(element, eventName, handler) { + var id = getEventID(element); + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (event.eventName && event.eventName != eventName) + return false; + + Event.extend(event); + handler.call(element, event) + }; + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var name = getDOMEventName(eventName); + + var wrapper = createWrapper(element, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, + + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + if (document.createEvent) { + var event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + var event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return event; + } + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize() +}); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards and John Resig. */ + + var timer, fired = false; + + function fireContentLoadedEvent() { + if (fired) return; + if (timer) window.clearInterval(timer); + document.fire("dom:loaded"); + fired = true; + } + + if (document.addEventListener) { + if (Prototype.Browser.WebKit) { + timer = window.setInterval(function() { + if (/loaded|complete/.test(document.readyState)) + fireContentLoadedEvent(); + }, 0); + + Event.observe(window, "load", fireContentLoadedEvent); + + } else { + document.addEventListener("DOMContentLoaded", + fireContentLoadedEvent, false); + } + + } else { + document.write("', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = new Object(); +var $continue = new Object(); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +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); +} + +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; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + 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) + 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 = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +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(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + 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) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + 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); + }, + + 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); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + 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; + }, + + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + 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); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + 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; + }, + + 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 + 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 = '' + html.stripScripts() + '
'; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 3; + break; + case 'TD': + div.innerHTML = '
' + html.stripScripts() + '
'; + 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; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(function() { + Object.extend(this, { + href: this._getAttr, + src: this._getAttr, + disabled: this._flag, + checked: this._flag, + readonly: this._flag, + multiple: this._flag + }); +}).call(Element._attributeTranslations.values); + +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 (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; +} + +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(); + 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); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + 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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s)/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +Object.extend(Form, Form.Methods); + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + 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; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +Object.extend(Form.Element, Form.Element.Methods); +Object.extend(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) +}); + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/assets/2007/4/28/prototype.js b/assets/2007/4/28/prototype.js new file mode 100644 index 000000000..1beb8a89a --- /dev/null +++ b/assets/2007/4/28/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1_rc4 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1_rc4', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: ']*>([\u0001-\uFFFF]*?)', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [( event || window.event)].concat(args).concat($A(arguments))); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +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); +} + +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; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + 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) + 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 = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +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(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + 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) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + 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); + }, + + 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); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + 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; + }, + + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + 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); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + 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; + }, + + 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 + 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 = '' + html.stripScripts() + '
'; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 3; + break; + case 'TD': + div.innerHTML = '
' + html.stripScripts() + '
'; + 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; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(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); + +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, { + "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; +} + +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(); + 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); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + 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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s)/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + 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; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/assets/2007/5/1/prototype.js b/assets/2007/5/1/prototype.js new file mode 100644 index 000000000..5d2100fac --- /dev/null +++ b/assets/2007/5/1/prototype.js @@ -0,0 +1,3271 @@ +/* Prototype JavaScript framework, version 1.5.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: ']*>([\u0001-\uFFFF]*?)', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +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); +} + +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; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +if (!window.Element) var Element = {}; + +Element.extend = function(element) { + var F = Prototype.BrowserFeatures; + 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) + 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 = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +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(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + 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) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + 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); + }, + + 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); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + 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; + }, + + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + 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); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + 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; + }, + + 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 + 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 = '' + html.stripScripts() + '
'; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 3; + break; + case 'TD': + div.innerHTML = '
' + html.stripScripts() + '
'; + 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; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(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); + +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, { + "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; +} + +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(); + 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); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + 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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + 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; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/assets/2007/5/11/bungee-book.jpg b/assets/2007/5/11/bungee-book.jpg new file mode 100644 index 000000000..78910c168 Binary files /dev/null and b/assets/2007/5/11/bungee-book.jpg differ diff --git a/assets/2007/5/11/bungee-book_1.jpg b/assets/2007/5/11/bungee-book_1.jpg new file mode 100644 index 000000000..78910c168 Binary files /dev/null and b/assets/2007/5/11/bungee-book_1.jpg differ diff --git a/assets/2007/5/11/bungee-book_1_thumb.jpg b/assets/2007/5/11/bungee-book_1_thumb.jpg new file mode 100644 index 000000000..8eebe42d7 Binary files /dev/null and b/assets/2007/5/11/bungee-book_1_thumb.jpg differ diff --git a/assets/2007/5/11/bungee-book_1_tiny.jpg b/assets/2007/5/11/bungee-book_1_tiny.jpg new file mode 100644 index 000000000..a774466d6 Binary files /dev/null and b/assets/2007/5/11/bungee-book_1_tiny.jpg differ diff --git a/assets/2007/5/11/bungee-book_thumb.jpg b/assets/2007/5/11/bungee-book_thumb.jpg new file mode 100644 index 000000000..8eebe42d7 Binary files /dev/null and b/assets/2007/5/11/bungee-book_thumb.jpg differ diff --git a/assets/2007/5/11/bungee-book_tiny.jpg b/assets/2007/5/11/bungee-book_tiny.jpg new file mode 100644 index 000000000..a774466d6 Binary files /dev/null and b/assets/2007/5/11/bungee-book_tiny.jpg differ diff --git a/assets/2007/5/11/crane3_cover150.jpg b/assets/2007/5/11/crane3_cover150.jpg new file mode 100644 index 000000000..3afad178c Binary files /dev/null and b/assets/2007/5/11/crane3_cover150.jpg differ diff --git a/assets/2007/5/11/crane3_cover150_1.jpg b/assets/2007/5/11/crane3_cover150_1.jpg new file mode 100644 index 000000000..3afad178c Binary files /dev/null and b/assets/2007/5/11/crane3_cover150_1.jpg differ diff --git a/assets/2007/5/11/crane3_cover150_1_thumb.jpg b/assets/2007/5/11/crane3_cover150_1_thumb.jpg new file mode 100644 index 000000000..0df31ced4 Binary files /dev/null and b/assets/2007/5/11/crane3_cover150_1_thumb.jpg differ diff --git a/assets/2007/5/11/crane3_cover150_1_tiny.jpg b/assets/2007/5/11/crane3_cover150_1_tiny.jpg new file mode 100644 index 000000000..e291ea2b2 Binary files /dev/null and b/assets/2007/5/11/crane3_cover150_1_tiny.jpg differ diff --git a/assets/2007/5/11/crane3_cover150_thumb.jpg b/assets/2007/5/11/crane3_cover150_thumb.jpg new file mode 100644 index 000000000..0df31ced4 Binary files /dev/null and b/assets/2007/5/11/crane3_cover150_thumb.jpg differ diff --git a/assets/2007/5/11/crane3_cover150_tiny.jpg b/assets/2007/5/11/crane3_cover150_tiny.jpg new file mode 100644 index 000000000..e291ea2b2 Binary files /dev/null and b/assets/2007/5/11/crane3_cover150_tiny.jpg differ diff --git a/assets/2007/5/12/prototype-dev-6728.js b/assets/2007/5/12/prototype-dev-6728.js new file mode 100644 index 000000000..f41cfccb2 --- /dev/null +++ b/assets/2007/5/12/prototype-dev-6728.js @@ -0,0 +1,3456 @@ +/* Prototype JavaScript framework, version 1.5.2_pre0 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.2_pre0', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: ']*>([\u0001-\uFFFF]*?)', + JSONFilter: /^\/\*-secure-\s*(.*)\s*\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Object.extend(Function.prototype, { + bind: function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } + }, + + bindAsEventListener: function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } + }, + + curry: function() { + var __method = this, args = $A(arguments); + return function() { + return __method.apply(this, args.concat($A(arguments))); + } + }, + + delay: function() { + var __method = this, args = $A(arguments), timeout = args.shift() * 1000; + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + }, + + wrap: function(wrapper) { + var __method = this; + return function() { + return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); + } + }, + + methodize: function() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + return __method.apply(null, [this].concat($A(arguments))); + }; + } +}); + +Function.prototype.defer = Function.prototype.delay.curry(0.01); + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = new Element('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || (/^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/.test(json))) + return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}; + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +function $A(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + function $A(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Array.from = $A; + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText, options = this.options; + + if (!options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (typeof options.insertion == 'string') + receiver.insert(response, options.insertion); + else options.insertion(receiver, response); + } + else receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) this.onComplete.bind(this).defer(); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +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); +} + +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; + for (var i = 0, length = children.length; i < length; i++) { + child = children[i]; + if (Element.hasClassName(child, className)) + elements.push(Element.extend(child)); + } + return elements; +}; + +/*--------------------------------------------------------------------------*/ + +(function() { + var element = this.Element; + this.Element = function(tagName, attributes) { + attributes = attributes || {}; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (Prototype.Browser.IE && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(this.Element, element || {}); +}).call(window); + +Element.cache = {}; + +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(); + html.evalScripts.bind(html).defer(); + return element; + }, + + replace: function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + var range = element.ownerDocument.createRange(); + range.selectNode(element); + element.parentNode.replaceChild( + range.createContextualFragment(html.stripScripts()), element); + } + html.evalScripts.bind(html).defer(); + return element; + }, + + insert: function(element, content, position) { + element = $(element); + position = (position || 'bottom').toLowerCase(); + var t = Element._insertionTranslations[position], range; + + if (content && content.ownerDocument === document) { + t.insert(element, content); + return element; + } + + content = content.toString(); + + range = element.ownerDocument.createRange(); + t.initializeRange(element, range); + t.insert(element, range.createContextualFragment(content.stripScripts())); + + content.evalScripts.bind(content).defer(); + return element; + }, + + wrap: function(element, wrapper) { + element = $(element); + wrapper = wrapper || 'div'; + if (typeof wrapper == 'string') wrapper = new Element(wrapper); + else Element.extend(wrapper); + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + 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); + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + if (!element.attributes) return null; + var t = Element._attributeTranslations.read; + 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); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = {}, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = value === undefined ? true : value; + + for (var attr in attributes) { + var name = t.names[attr] || attr, value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + 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; + }, + + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + 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); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + 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; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + var offsets = element.positionedOffset(); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = source.viewportOffset(); + + // find coordinate system to use + element = $(element); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(element,'position') == 'absolute') { + parent = element.getOffsetParent(); + delta = parent.getViewportOffset(); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) element.style.width = source.offsetWidth + 'px'; + if(options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Object.extend(Element.Methods, { + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: {} + } +}; + + +if (!document.createRange || Prototype.Browser.Opera) { + Element.Methods.insert = function(element, content, position) { + element = $(element); + position = (position || 'bottom').toLowerCase(); + var t = Element._insertionTranslations, pos = t[position], tagName; + + if (content && content.ownerDocument === document) { + pos.insert(element, content); + return element; + } + + content = content.toString(); + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + if (t.tags[tagName]) { + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + if (position == 'top' || position == 'after') fragments.reverse(); + fragments.each(pos.insert.curry(element)); + } + else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); + + content.evalScripts.bind(content).defer(); + return element; + } +} + +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); + } + }; + Element.Methods._readAttribute = Element.Methods.readAttribute; + Element.Methods.readAttribute = function(element, attribute) { + if (attribute == 'title') return element.title; + return Element._readAttribute(element, attribute); + }; +} + +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; + }; + + Element._attributeTranslations = { + read: { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } + } + }; + + Element._attributeTranslations.write = { + names: Object.extend({ + 'class': 'className', + 'for': 'htmlFor' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + (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.read.values); +} + +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; + }; +} + +else if (Prototype.Browser.WebKit) { + // Safari returns margins on body which is incorrect if the child is absolutely + // positioned. For performance reasons, redefine Position.cumulativeOffset for + // KHTML/WebKit only. + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +if (Prototype.Browser.IE || Prototype.Browser.Opera) { + // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements + Element.Methods.update = function(element, html) { + element = $(element); + html = typeof html == 'undefined' ? '' : html.toString(); + var tagName = element.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + Element._getContentFromAnonymousElement(tagName, html.stripScripts()) + .each(function(node) { element.appendChild(node) }); + } + else element.innerHTML = html.stripScripts(); + + html.evalScripts.bind(html).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'); t = Element._insertionTranslations.tags[tagName] + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: { + adjacency: 'beforeBegin', + insert: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + initializeRange: function(element, range) { + range.setStartBefore(element); + } + }, + top: { + adjacency: 'afterBegin', + insert: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + initializeRange: function(element, range) { + range.selectNodeContents(element); + range.collapse(true); + } + }, + bottom: { + adjacency: 'beforeEnd', + insert: function(element, node) { + element.appendChild(node); + } + }, + after: { + adjacency: 'afterEnd', + insert: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + initializeRange: function(element, range) { + range.setStartAfter(element); + } + }, + tags: { + TABLE: ['', '
', 1], + TBODY: ['', '
', 2], + TR: ['', '
', 3], + TD: ['
', '
', 4], + SELECT: ['', 1] + } +}; + +(function() { + this.bottom.initializeRange = this.top.initializeRange; + Object.extend(this.tags, { + THEAD: this.tags.TBODY, + TFOOT: this.tags.TBODY, + TH: this.tags.TD + }); +}).call(Element._insertionTranslations); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + var t = Element._attributeTranslations.read, node; + attribute = t.names[attribute] || attribute; + node = $(element).getAttributeNode(attribute); + return node && node.specified; + } +}; + +Element.Methods.ByTag = {}; + +Object.extend(Element, Element.Methods); + +Element.extend = (function() { + if (Prototype.BrowserFeatures.SpecificElementExtensions) + return Prototype.K; + + var Methods = {}, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || element._extendedByPrototype || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName, property, value; + + // extend methods for specific tags + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + for (property in methods) { + value = methods[property]; + if (typeof value == 'function' && !(property in element)) + element[property] = value.methodize(); + } + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + // extend methods for all tags (Safari doesn't need this) + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +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, { + "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; + for (var property in methods) { + var value = methods[property]; + if (typeof value != 'function') continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + 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; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = {}; +}; + +/*--------------------------------------------------------------------------*/ + +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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + 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; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +/*------------------------------- DEPRECATED -------------------------------*/ + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, content, 'before'); + }, + + Top: function(element, content) { + return Element.insert(element, content, 'top'); + }, + + Bottom: function(element, content) { + return Element.insert(element, content, 'bottom'); + }, + + After: function(element, content) { + return Element.insert(element, content, 'after'); + } +} + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +// This should be moved to script.aculo.us; notice the deprecated methods +// further below, that map to the newer Element methods. +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + // Deprecation layer -- use newer Element methods now (1.5.2). + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || {}; + return Element.clonePosition(target, source, options); + } +} +/*--------------------------------------------------------------------------*/ + +Element.addMethods(); \ No newline at end of file diff --git a/assets/2007/5/22/ar-log.gif b/assets/2007/5/22/ar-log.gif new file mode 100644 index 000000000..1f91ecbf2 Binary files /dev/null and b/assets/2007/5/22/ar-log.gif differ diff --git a/assets/2007/5/22/ar-log_thumb.gif b/assets/2007/5/22/ar-log_thumb.gif new file mode 100644 index 000000000..dcd46d4b9 Binary files /dev/null and b/assets/2007/5/22/ar-log_thumb.gif differ diff --git a/assets/2007/5/22/ar-log_tiny.gif b/assets/2007/5/22/ar-log_tiny.gif new file mode 100644 index 000000000..a65c6434a Binary files /dev/null and b/assets/2007/5/22/ar-log_tiny.gif differ diff --git a/assets/2007/5/22/lh-white-logo.gif b/assets/2007/5/22/lh-white-logo.gif new file mode 100644 index 000000000..affced3dd Binary files /dev/null and b/assets/2007/5/22/lh-white-logo.gif differ diff --git a/assets/2007/5/22/lh-white-logo_thumb.gif b/assets/2007/5/22/lh-white-logo_thumb.gif new file mode 100644 index 000000000..429c60e7c Binary files /dev/null and b/assets/2007/5/22/lh-white-logo_thumb.gif differ diff --git a/assets/2007/5/22/lh-white-logo_tiny.gif b/assets/2007/5/22/lh-white-logo_tiny.gif new file mode 100644 index 000000000..53bbda973 Binary files /dev/null and b/assets/2007/5/22/lh-white-logo_tiny.gif differ diff --git a/assets/2007/5/7/bungee-book.jpg b/assets/2007/5/7/bungee-book.jpg new file mode 100644 index 000000000..78910c168 Binary files /dev/null and b/assets/2007/5/7/bungee-book.jpg differ diff --git a/assets/2007/5/7/bungee-book_thumb.jpg b/assets/2007/5/7/bungee-book_thumb.jpg new file mode 100644 index 000000000..8eebe42d7 Binary files /dev/null and b/assets/2007/5/7/bungee-book_thumb.jpg differ diff --git a/assets/2007/5/7/bungee-book_tiny.jpg b/assets/2007/5/7/bungee-book_tiny.jpg new file mode 100644 index 000000000..a774466d6 Binary files /dev/null and b/assets/2007/5/7/bungee-book_tiny.jpg differ diff --git a/assets/2007/6/15/flag-gam-nameplate.png b/assets/2007/6/15/flag-gam-nameplate.png new file mode 100644 index 000000000..78fe7e7d4 Binary files /dev/null and b/assets/2007/6/15/flag-gam-nameplate.png differ diff --git a/assets/2007/6/15/flag-gam-nameplate_thumb.png b/assets/2007/6/15/flag-gam-nameplate_thumb.png new file mode 100644 index 000000000..8f32b458d Binary files /dev/null and b/assets/2007/6/15/flag-gam-nameplate_thumb.png differ diff --git a/assets/2007/6/15/flag-gam-nameplate_tiny.png b/assets/2007/6/15/flag-gam-nameplate_tiny.png new file mode 100644 index 000000000..72542fa6a Binary files /dev/null and b/assets/2007/6/15/flag-gam-nameplate_tiny.png differ diff --git a/assets/2007/6/20/prototype-151-api.pdf b/assets/2007/6/20/prototype-151-api.pdf new file mode 100644 index 000000000..3b2a85ccf Binary files /dev/null and b/assets/2007/6/20/prototype-151-api.pdf differ diff --git a/assets/2007/6/20/prototype.js b/assets/2007/6/20/prototype.js new file mode 100644 index 000000000..a3f21ac79 --- /dev/null +++ b/assets/2007/6/20/prototype.js @@ -0,0 +1,3277 @@ +/* Prototype JavaScript framework, version 1.5.1.1 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * +/*--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.5.1.1', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1 + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + (document.createElement('div').__proto__ !== + document.createElement('form').__proto__) + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +} + +var Class = { + create: function() { + return function() { + this.initialize.apply(this, arguments); + } + } +} + +var Abstract = new Object(); + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +} + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch(type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (object.ownerDocument === document) return; + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + return '{' + results.join(', ') + '}'; + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({}, object); + } +}); + +Function.prototype.bind = function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } +} + +Function.prototype.bindAsEventListener = function(object) { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } +} + +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) {} + } + + return returnValue; + } +} + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create(); +PeriodicalExecuter.prototype = { + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +} +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return this; + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : this; + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = document.createElement('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return {}; + + return match[1].split(separator || '&').inject({}, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (hash[key].constructor != Array) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + isJSON: function() { + var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (typeof replacement == 'function') return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +} + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + return this.template.gsub(this.pattern, function(match) { + var before = match[1]; + if (before == '\\') return match[2]; + return before + String.interpret(object[match[3]]); + }); + } +} + +var $break = {}, $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Enumerable = { + each: function(iterator) { + var index = 0; + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator) { + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.map(iterator); + }, + + all: function(iterator) { + var result = true; + this.each(function(value, index) { + result = result && !!(iterator || Prototype.K)(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator) { + var result = false; + this.each(function(value, index) { + if (result = !!(iterator || Prototype.K)(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator) { + var results = []; + this.each(function(value, index) { + results.push((iterator || Prototype.K)(value, index)); + }); + return results; + }, + + detect: function(iterator) { + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator) { + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(pattern, iterator) { + var results = []; + this.each(function(value, index) { + var stringValue = value.toString(); + if (stringValue.match(pattern)) + results.push((iterator || Prototype.K)(value, index)); + }) + return results; + }, + + include: function(object) { + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator) { + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator) { + var result; + this.each(function(value, index) { + value = (iterator || Prototype.K)(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator) { + var trues = [], falses = []; + this.each(function(value, index) { + ((iterator || Prototype.K)(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value, index) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator) { + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator) { + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (typeof args.last() == 'function') + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +} + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray +}); +var $A = Array.from = function(iterable) { + if (!iterable) return []; + if (iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + $A = Array.from = function(iterable) { + if (!iterable) return []; + if (!(typeof iterable == 'function' && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(value && value.constructor == Array ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + indexOf: function(object) { + for (var i = 0, length = this.length; i < length; i++) + if (this[i] == object) return i; + return -1; + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (arguments[i].constructor == Array) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + } +} +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || {}); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (value.constructor == Array) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +} + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (result.constructor != Array) result = [result]; + result.push(value) + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +} + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (typeof responder[callback] == 'function') { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) {} + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() {}; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '' + } + Object.extend(this.options, options || {}); + + this.options.method = this.options.method.toLowerCase(); + if (typeof this.options.parameters == 'string') + this.options.parameters = this.options.parameters.toQueryParams(); + } +} + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + if (this.options.onCreate) this.options.onCreate(this.transport); + Ajax.Responders.dispatch('onCreate', this, this.transport); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) + setTimeout(function() { this.respondToReadyState(1) }.bind(this), 10); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (typeof extras.push == 'function') + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + return !this.transport.status + || (this.transport.status >= 200 && this.transport.status < 300); + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState]; + var transport = this.transport, json = this.evalJSON(); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + this.transport.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(transport, json); + } catch (e) { + this.dispatchException(e); + } + + var contentType = this.getHeader('Content-type'); + if (contentType && contentType.strip(). + match(/^(text|application)\/(x-)?(java|ecma)script(;.*)?$/i)) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(transport, json); + Ajax.Responders.dispatch('on' + state, this, transport, json); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalJSON: function() { + try { + var json = this.getHeader('X-JSON'); + return json ? json.evalJSON() : null; + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + } + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(transport, param) { + this.updateContent(); + onComplete(transport, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function() { + var receiver = this.container[this.success() ? 'success' : 'failure']; + var response = this.transport.responseText; + + if (!this.options.evalScripts) response = response.stripScripts(); + + if (receiver = $(receiver)) { + if (this.options.insertion) + new this.options.insertion(receiver, response); + else + receiver.update(response); + } + + if (this.success()) { + if (this.onComplete) + setTimeout(this.onComplete.bind(this), 10); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = {}; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(request) { + if (this.options.decay) { + this.decay = (request.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = request.responseText; + } + this.timer = setTimeout(this.onTimerEvent.bind(this), + this.decay * this.frequency * 1000); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +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); +} + +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; + 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) + 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 = Prototype.emptyFunction; + return element; +}; + +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +}; + +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(); + if (element.outerHTML) { + element.outerHTML = html.stripScripts(); + } else { + 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) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + 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); + }, + + 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); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + 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; + }, + + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + 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); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + 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; + }, + + 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 + 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 = '' + html.stripScripts() + '
'; + depth = 2; + break; + case 'TR': + div.innerHTML = '' + html.stripScripts() + '
'; + depth = 3; + break; + case 'TD': + div.innerHTML = '
' + html.stripScripts() + '
'; + 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; + }; +} + +Element._attributeTranslations = { + names: { + colspan: "colSpan", + rowspan: "rowSpan", + valign: "vAlign", + datetime: "dateTime", + accesskey: "accessKey", + tabindex: "tabIndex", + enctype: "encType", + maxlength: "maxLength", + readonly: "readOnly", + longdesc: "longDesc" + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + var node = element.getAttributeNode('title'); + return node.specified ? node.nodeValue : null; + } + } +}; + +(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); + +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, { + "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; +} + +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(); + 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); + }, + + contentFromAnonymousTable: function() { + var div = document.createElement('div'); + div.innerHTML = '' + this.content + '
'; + 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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; return; + } + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(typeof c[i] == 'function' ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(typeof x[i] == 'function' ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + return this.findElements(document).include(element); + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}; + +Object.extend(Selector, { + _cache: {}, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (typeof h === 'function') return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = typeof x[i] == 'function' ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\]]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!nodes && root == document) return targetNode ? [targetNode] : []; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (typeof expression == 'number') { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, getHash) { + var data = elements.inject({}, function(result, element) { + if (!element.disabled && element.name) { + var key = element.name, value = $(element).getValue(); + if (value != null) { + if (key in result) { + if (result[key].constructor != Array) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return getHash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, getHash) { + return Form.serializeElements(Form.getElements(form), getHash); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + return $(form).getElements().find(function(element) { + return element.type != 'hidden' && !element.disabled && + ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || {}); + + var params = options.parameters; + options.parameters = form.serialize(true); + + if (params) { + if (typeof params == 'string') params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(form.readAttribute('action'), options); + } +} + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +} + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = {}; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + 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; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +} + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element); + default: + return Form.Element.Serializers.textarea(element); + } + }, + + inputSelector: function(element) { + return element.checked ? element.value : null; + }, + + textarea: function(element) { + return element.value; + }, + + select: function(element) { + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +} + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() {} +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = ('string' == typeof this.lastValue && 'string' == typeof value + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +} + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() {} +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +} + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) { + var Event = new Object(); +} + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + + element: function(event) { + return $(event.target || event.srcElement); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointerX: function(event) { + return event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)); + }, + + pointerY: function(event) { + return event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)); + }, + + stop: function(event) { + if (event.preventDefault) { + event.preventDefault(); + event.stopPropagation(); + } else { + event.returnValue = false; + event.cancelBubble = true; + } + }, + + // find the first node with the given tagName, starting from the + // node the event was triggered on; traverses the DOM upwards + findElement: function(event, tagName) { + var element = Event.element(event); + while (element.parentNode && (!element.tagName || + (element.tagName.toUpperCase() != tagName.toUpperCase()))) + element = element.parentNode; + return element; + }, + + observers: false, + + _observeAndCache: function(element, name, observer, useCapture) { + if (!this.observers) this.observers = []; + if (element.addEventListener) { + this.observers.push([element, name, observer, useCapture]); + element.addEventListener(name, observer, useCapture); + } else if (element.attachEvent) { + this.observers.push([element, name, observer, useCapture]); + element.attachEvent('on' + name, observer); + } + }, + + unloadCache: function() { + if (!Event.observers) return; + for (var i = 0, length = Event.observers.length; i < length; i++) { + Event.stopObserving.apply(this, Event.observers[i]); + Event.observers[i][0] = null; + } + Event.observers = false; + }, + + observe: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + Event._observeAndCache(element, name, observer, useCapture); + }, + + stopObserving: function(element, name, observer, useCapture) { + element = $(element); + useCapture = useCapture || false; + + if (name == 'keypress' && + (Prototype.Browser.WebKit || element.attachEvent)) + name = 'keydown'; + + if (element.removeEventListener) { + element.removeEventListener(name, observer, useCapture); + } else if (element.detachEvent) { + try { + element.detachEvent('on' + name, observer); + } catch (e) {} + } + } +}); + +/* prevent memory leaks in IE */ +if (Prototype.Browser.IE) + Event.observe(window, 'unload', Event.unloadCache, false); +var Position = { + // set to true if needed, warning: firefox performance problems + // NOT neeeded for page scrolling, only if draggable contained in + // scrollable elements + includeScrollOffsets: false, + + // must be called before calling withinIncludingScrolloffset, every time the + // page is scrolled + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + realOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return [valueL, valueT]; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return [valueL, valueT]; + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if(element.tagName=='BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return [valueL, valueT]; + }, + + offsetParent: function(element) { + if (element.offsetParent) return element.offsetParent; + if (element == document.body) return element; + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return element; + + return document.body; + }, + + // caches x/y coordinate pair to use with overlap + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = this.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = this.realOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = this.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + // within must be called directly before + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + page: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body) + if (Element.getStyle(element,'position')=='absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!window.opera || element.tagName=='BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return [valueL, valueT]; + }, + + clone: function(source, target) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || {}) + + // find page position of source + source = $(source); + var p = Position.page(source); + + // find coordinate system to use + target = $(target); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(target,'position') == 'absolute') { + parent = Position.offsetParent(target); + delta = Position.page(parent); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if(options.setWidth) target.style.width = source.offsetWidth + 'px'; + if(options.setHeight) target.style.height = source.offsetHeight + 'px'; + }, + + absolutize: function(element) { + element = $(element); + if (element.style.position == 'absolute') return; + Position.prepare(); + + var offsets = Position.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + }, + + relativize: function(element) { + element = $(element); + if (element.style.position == 'relative') return; + Position.prepare(); + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + } +} + +// Safari returns margins on body which is incorrect if the child is absolutely +// positioned. For performance reasons, redefine Position.cumulativeOffset for +// KHTML/WebKit only. +if (Prototype.Browser.WebKit) { + Position.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return [valueL, valueT]; + } +} + +Element.addMethods(); \ No newline at end of file diff --git a/assets/2007/6/26/logo_home_sm.jpg b/assets/2007/6/26/logo_home_sm.jpg new file mode 100644 index 000000000..f461dc2cc Binary files /dev/null and b/assets/2007/6/26/logo_home_sm.jpg differ diff --git a/assets/2007/6/26/logo_home_sm_thumb.jpg b/assets/2007/6/26/logo_home_sm_thumb.jpg new file mode 100644 index 000000000..ea8dd68e4 Binary files /dev/null and b/assets/2007/6/26/logo_home_sm_thumb.jpg differ diff --git a/assets/2007/6/26/logo_home_sm_tiny.jpg b/assets/2007/6/26/logo_home_sm_tiny.jpg new file mode 100644 index 000000000..f6861c2d0 Binary files /dev/null and b/assets/2007/6/26/logo_home_sm_tiny.jpg differ diff --git a/assets/2007/6/3/Blinklist.gif b/assets/2007/6/3/Blinklist.gif new file mode 100644 index 000000000..719115663 Binary files /dev/null and b/assets/2007/6/3/Blinklist.gif differ diff --git a/assets/2007/6/3/Blinklist_thumb.gif b/assets/2007/6/3/Blinklist_thumb.gif new file mode 100644 index 000000000..b29db81c5 Binary files /dev/null and b/assets/2007/6/3/Blinklist_thumb.gif differ diff --git a/assets/2007/6/3/Blinklist_tiny.gif b/assets/2007/6/3/Blinklist_tiny.gif new file mode 100644 index 000000000..d6149160d Binary files /dev/null and b/assets/2007/6/3/Blinklist_tiny.gif differ diff --git a/assets/2007/6/3/a.com_logo_th.jpg b/assets/2007/6/3/a.com_logo_th.jpg new file mode 100644 index 000000000..29cca36cd Binary files /dev/null and b/assets/2007/6/3/a.com_logo_th.jpg differ diff --git a/assets/2007/6/3/a.com_logo_th_thumb.jpg b/assets/2007/6/3/a.com_logo_th_thumb.jpg new file mode 100644 index 000000000..74f8a8775 Binary files /dev/null and b/assets/2007/6/3/a.com_logo_th_thumb.jpg differ diff --git a/assets/2007/6/3/a.com_logo_th_tiny.jpg b/assets/2007/6/3/a.com_logo_th_tiny.jpg new file mode 100644 index 000000000..d13472ffc Binary files /dev/null and b/assets/2007/6/3/a.com_logo_th_tiny.jpg differ diff --git a/assets/2007/6/3/badge_red.gif b/assets/2007/6/3/badge_red.gif new file mode 100644 index 000000000..598a41531 Binary files /dev/null and b/assets/2007/6/3/badge_red.gif differ diff --git a/assets/2007/6/3/badge_red_rev.gif b/assets/2007/6/3/badge_red_rev.gif new file mode 100644 index 000000000..a5f35f257 Binary files /dev/null and b/assets/2007/6/3/badge_red_rev.gif differ diff --git a/assets/2007/6/3/badge_red_rev_thumb.gif b/assets/2007/6/3/badge_red_rev_thumb.gif new file mode 100644 index 000000000..18750f637 Binary files /dev/null and b/assets/2007/6/3/badge_red_rev_thumb.gif differ diff --git a/assets/2007/6/3/badge_red_rev_tiny.gif b/assets/2007/6/3/badge_red_rev_tiny.gif new file mode 100644 index 000000000..13a429793 Binary files /dev/null and b/assets/2007/6/3/badge_red_rev_tiny.gif differ diff --git a/assets/2007/6/3/badge_red_thumb.gif b/assets/2007/6/3/badge_red_thumb.gif new file mode 100644 index 000000000..e367d9add Binary files /dev/null and b/assets/2007/6/3/badge_red_thumb.gif differ diff --git a/assets/2007/6/3/badge_red_tiny.gif b/assets/2007/6/3/badge_red_tiny.gif new file mode 100644 index 000000000..f1ce7e3f2 Binary files /dev/null and b/assets/2007/6/3/badge_red_tiny.gif differ diff --git a/assets/2007/6/3/dailymotion.png b/assets/2007/6/3/dailymotion.png new file mode 100644 index 000000000..2e51a337b Binary files /dev/null and b/assets/2007/6/3/dailymotion.png differ diff --git a/assets/2007/6/3/dailymotion_thumb.png b/assets/2007/6/3/dailymotion_thumb.png new file mode 100644 index 000000000..d271c4c04 Binary files /dev/null and b/assets/2007/6/3/dailymotion_thumb.png differ diff --git a/assets/2007/6/3/dailymotion_tiny.png b/assets/2007/6/3/dailymotion_tiny.png new file mode 100644 index 000000000..105924c5a Binary files /dev/null and b/assets/2007/6/3/dailymotion_tiny.png differ diff --git a/assets/2007/6/3/grandcentral.jpg b/assets/2007/6/3/grandcentral.jpg new file mode 100644 index 000000000..0f46f4357 Binary files /dev/null and b/assets/2007/6/3/grandcentral.jpg differ diff --git a/assets/2007/6/3/grandcentral_thumb.jpg b/assets/2007/6/3/grandcentral_thumb.jpg new file mode 100644 index 000000000..34c387035 Binary files /dev/null and b/assets/2007/6/3/grandcentral_thumb.jpg differ diff --git a/assets/2007/6/3/grandcentral_tiny.jpg b/assets/2007/6/3/grandcentral_tiny.jpg new file mode 100644 index 000000000..347782a11 Binary files /dev/null and b/assets/2007/6/3/grandcentral_tiny.jpg differ diff --git a/assets/2007/6/3/hdr-logo-mapquest b/assets/2007/6/3/hdr-logo-mapquest new file mode 100644 index 000000000..25f1d0591 Binary files /dev/null and b/assets/2007/6/3/hdr-logo-mapquest differ diff --git a/assets/2007/6/3/hdr-logo-mapquest.gif b/assets/2007/6/3/hdr-logo-mapquest.gif new file mode 100644 index 000000000..25f1d0591 Binary files /dev/null and b/assets/2007/6/3/hdr-logo-mapquest.gif differ diff --git a/assets/2007/6/3/hdr-logo-mapquest_thumb b/assets/2007/6/3/hdr-logo-mapquest_thumb new file mode 100644 index 000000000..1c269f743 Binary files /dev/null and b/assets/2007/6/3/hdr-logo-mapquest_thumb differ diff --git a/assets/2007/6/3/hdr-logo-mapquest_thumb.gif b/assets/2007/6/3/hdr-logo-mapquest_thumb.gif new file mode 100644 index 000000000..1c269f743 Binary files /dev/null and b/assets/2007/6/3/hdr-logo-mapquest_thumb.gif differ diff --git a/assets/2007/6/3/hdr-logo-mapquest_tiny b/assets/2007/6/3/hdr-logo-mapquest_tiny new file mode 100644 index 000000000..5901593c5 Binary files /dev/null and b/assets/2007/6/3/hdr-logo-mapquest_tiny differ diff --git a/assets/2007/6/3/hdr-logo-mapquest_tiny.gif b/assets/2007/6/3/hdr-logo-mapquest_tiny.gif new file mode 100644 index 000000000..5901593c5 Binary files /dev/null and b/assets/2007/6/3/hdr-logo-mapquest_tiny.gif differ diff --git a/assets/2007/6/3/header.gif b/assets/2007/6/3/header.gif new file mode 100644 index 000000000..25acd5e54 Binary files /dev/null and b/assets/2007/6/3/header.gif differ diff --git a/assets/2007/6/3/header.gif_1166958154 b/assets/2007/6/3/header.gif_1166958154 new file mode 100644 index 000000000..25acd5e54 Binary files /dev/null and b/assets/2007/6/3/header.gif_1166958154 differ diff --git a/assets/2007/6/3/header_thumb.gif b/assets/2007/6/3/header_thumb.gif new file mode 100644 index 000000000..8b1948ef8 Binary files /dev/null and b/assets/2007/6/3/header_thumb.gif differ diff --git a/assets/2007/6/3/header_thumb.gif_1166958154 b/assets/2007/6/3/header_thumb.gif_1166958154 new file mode 100644 index 000000000..8b1948ef8 Binary files /dev/null and b/assets/2007/6/3/header_thumb.gif_1166958154 differ diff --git a/assets/2007/6/3/header_tiny.gif b/assets/2007/6/3/header_tiny.gif new file mode 100644 index 000000000..394e9e0c1 Binary files /dev/null and b/assets/2007/6/3/header_tiny.gif differ diff --git a/assets/2007/6/3/header_tiny.gif_1166958154 b/assets/2007/6/3/header_tiny.gif_1166958154 new file mode 100644 index 000000000..394e9e0c1 Binary files /dev/null and b/assets/2007/6/3/header_tiny.gif_1166958154 differ diff --git a/assets/2007/6/3/hi5.gif b/assets/2007/6/3/hi5.gif new file mode 100644 index 000000000..027298a2d Binary files /dev/null and b/assets/2007/6/3/hi5.gif differ diff --git a/assets/2007/6/3/hi5_thumb.gif b/assets/2007/6/3/hi5_thumb.gif new file mode 100644 index 000000000..9ffe241ce Binary files /dev/null and b/assets/2007/6/3/hi5_thumb.gif differ diff --git a/assets/2007/6/3/hi5_tiny.gif b/assets/2007/6/3/hi5_tiny.gif new file mode 100644 index 000000000..8c79cd6b2 Binary files /dev/null and b/assets/2007/6/3/hi5_tiny.gif differ diff --git a/assets/2007/6/3/iq_betalogo.gif b/assets/2007/6/3/iq_betalogo.gif new file mode 100644 index 000000000..5eb3a2aff Binary files /dev/null and b/assets/2007/6/3/iq_betalogo.gif differ diff --git a/assets/2007/6/3/iq_betalogo_thumb.gif b/assets/2007/6/3/iq_betalogo_thumb.gif new file mode 100644 index 000000000..3bd39b4cd Binary files /dev/null and b/assets/2007/6/3/iq_betalogo_thumb.gif differ diff --git a/assets/2007/6/3/iq_betalogo_tiny.gif b/assets/2007/6/3/iq_betalogo_tiny.gif new file mode 100644 index 000000000..88ad1612d Binary files /dev/null and b/assets/2007/6/3/iq_betalogo_tiny.gif differ diff --git a/assets/2007/6/3/istockphoto.jpg b/assets/2007/6/3/istockphoto.jpg new file mode 100644 index 000000000..2eafe85f0 Binary files /dev/null and b/assets/2007/6/3/istockphoto.jpg differ diff --git a/assets/2007/6/3/istockphoto_thumb.jpg b/assets/2007/6/3/istockphoto_thumb.jpg new file mode 100644 index 000000000..86d048197 Binary files /dev/null and b/assets/2007/6/3/istockphoto_thumb.jpg differ diff --git a/assets/2007/6/3/istockphoto_tiny.jpg b/assets/2007/6/3/istockphoto_tiny.jpg new file mode 100644 index 000000000..471e5137c Binary files /dev/null and b/assets/2007/6/3/istockphoto_tiny.jpg differ diff --git a/assets/2007/6/3/logo-2.gif b/assets/2007/6/3/logo-2.gif new file mode 100644 index 000000000..c91525db6 Binary files /dev/null and b/assets/2007/6/3/logo-2.gif differ diff --git a/assets/2007/6/3/logo-2_thumb.gif b/assets/2007/6/3/logo-2_thumb.gif new file mode 100644 index 000000000..0e1c179f0 Binary files /dev/null and b/assets/2007/6/3/logo-2_thumb.gif differ diff --git a/assets/2007/6/3/logo-2_tiny.gif b/assets/2007/6/3/logo-2_tiny.gif new file mode 100644 index 000000000..0f9488889 Binary files /dev/null and b/assets/2007/6/3/logo-2_tiny.gif differ diff --git a/assets/2007/6/3/logo-big.gif b/assets/2007/6/3/logo-big.gif new file mode 100644 index 000000000..ad1d682a5 Binary files /dev/null and b/assets/2007/6/3/logo-big.gif differ diff --git a/assets/2007/6/3/logo-big_thumb.gif b/assets/2007/6/3/logo-big_thumb.gif new file mode 100644 index 000000000..f90cae701 Binary files /dev/null and b/assets/2007/6/3/logo-big_thumb.gif differ diff --git a/assets/2007/6/3/logo-big_tiny.gif b/assets/2007/6/3/logo-big_tiny.gif new file mode 100644 index 000000000..a61776315 Binary files /dev/null and b/assets/2007/6/3/logo-big_tiny.gif differ diff --git a/assets/2007/6/3/logo-odeo.gif b/assets/2007/6/3/logo-odeo.gif new file mode 100644 index 000000000..7e3123bb8 Binary files /dev/null and b/assets/2007/6/3/logo-odeo.gif differ diff --git a/assets/2007/6/3/logo-odeo_thumb.gif b/assets/2007/6/3/logo-odeo_thumb.gif new file mode 100644 index 000000000..57c7fd1e0 Binary files /dev/null and b/assets/2007/6/3/logo-odeo_thumb.gif differ diff --git a/assets/2007/6/3/logo-odeo_tiny.gif b/assets/2007/6/3/logo-odeo_tiny.gif new file mode 100644 index 000000000..fe7d952ea Binary files /dev/null and b/assets/2007/6/3/logo-odeo_tiny.gif differ diff --git a/assets/2007/6/3/logo.gif b/assets/2007/6/3/logo.gif new file mode 100644 index 000000000..de4bb4a3f Binary files /dev/null and b/assets/2007/6/3/logo.gif differ diff --git a/assets/2007/6/3/logo.png b/assets/2007/6/3/logo.png new file mode 100644 index 000000000..7f93c90ff Binary files /dev/null and b/assets/2007/6/3/logo.png differ diff --git a/assets/2007/6/3/logo_1.gif b/assets/2007/6/3/logo_1.gif new file mode 100644 index 000000000..8765bfaa0 Binary files /dev/null and b/assets/2007/6/3/logo_1.gif differ diff --git a/assets/2007/6/3/logo_182x40_000000_24bit.png b/assets/2007/6/3/logo_182x40_000000_24bit.png new file mode 100644 index 000000000..9cf387d1d Binary files /dev/null and b/assets/2007/6/3/logo_182x40_000000_24bit.png differ diff --git a/assets/2007/6/3/logo_182x40_000000_24bit_thumb.png b/assets/2007/6/3/logo_182x40_000000_24bit_thumb.png new file mode 100644 index 000000000..ab730383d Binary files /dev/null and b/assets/2007/6/3/logo_182x40_000000_24bit_thumb.png differ diff --git a/assets/2007/6/3/logo_182x40_000000_24bit_tiny.png b/assets/2007/6/3/logo_182x40_000000_24bit_tiny.png new file mode 100644 index 000000000..da032972c Binary files /dev/null and b/assets/2007/6/3/logo_182x40_000000_24bit_tiny.png differ diff --git a/assets/2007/6/3/logo_1_thumb.gif b/assets/2007/6/3/logo_1_thumb.gif new file mode 100644 index 000000000..879d3b57e Binary files /dev/null and b/assets/2007/6/3/logo_1_thumb.gif differ diff --git a/assets/2007/6/3/logo_1_tiny.gif b/assets/2007/6/3/logo_1_tiny.gif new file mode 100644 index 000000000..2a8215d16 Binary files /dev/null and b/assets/2007/6/3/logo_1_tiny.gif differ diff --git a/assets/2007/6/3/logo_2.gif b/assets/2007/6/3/logo_2.gif new file mode 100644 index 000000000..bc83736b0 Binary files /dev/null and b/assets/2007/6/3/logo_2.gif differ diff --git a/assets/2007/6/3/logo_2_thumb.gif b/assets/2007/6/3/logo_2_thumb.gif new file mode 100644 index 000000000..0f8936102 Binary files /dev/null and b/assets/2007/6/3/logo_2_thumb.gif differ diff --git a/assets/2007/6/3/logo_2_tiny.gif b/assets/2007/6/3/logo_2_tiny.gif new file mode 100644 index 000000000..07cee39a8 Binary files /dev/null and b/assets/2007/6/3/logo_2_tiny.gif differ diff --git a/assets/2007/6/3/logo_beta.gif b/assets/2007/6/3/logo_beta.gif new file mode 100644 index 000000000..2982d780c Binary files /dev/null and b/assets/2007/6/3/logo_beta.gif differ diff --git a/assets/2007/6/3/logo_beta_thumb.gif b/assets/2007/6/3/logo_beta_thumb.gif new file mode 100644 index 000000000..66f37bcd7 Binary files /dev/null and b/assets/2007/6/3/logo_beta_thumb.gif differ diff --git a/assets/2007/6/3/logo_beta_tiny.gif b/assets/2007/6/3/logo_beta_tiny.gif new file mode 100644 index 000000000..917044d4e Binary files /dev/null and b/assets/2007/6/3/logo_beta_tiny.gif differ diff --git a/assets/2007/6/3/logo_h_sm.gif b/assets/2007/6/3/logo_h_sm.gif new file mode 100644 index 000000000..6652aed84 Binary files /dev/null and b/assets/2007/6/3/logo_h_sm.gif differ diff --git a/assets/2007/6/3/logo_h_sm_thumb.gif b/assets/2007/6/3/logo_h_sm_thumb.gif new file mode 100644 index 000000000..a4ad46fb0 Binary files /dev/null and b/assets/2007/6/3/logo_h_sm_thumb.gif differ diff --git a/assets/2007/6/3/logo_h_sm_tiny.gif b/assets/2007/6/3/logo_h_sm_tiny.gif new file mode 100644 index 000000000..68dff803f Binary files /dev/null and b/assets/2007/6/3/logo_h_sm_tiny.gif differ diff --git a/assets/2007/6/3/logo_skyrockblog.jpg b/assets/2007/6/3/logo_skyrockblog.jpg new file mode 100644 index 000000000..07a8123cf Binary files /dev/null and b/assets/2007/6/3/logo_skyrockblog.jpg differ diff --git a/assets/2007/6/3/logo_skyrockblog_thumb.jpg b/assets/2007/6/3/logo_skyrockblog_thumb.jpg new file mode 100644 index 000000000..23a8d1759 Binary files /dev/null and b/assets/2007/6/3/logo_skyrockblog_thumb.jpg differ diff --git a/assets/2007/6/3/logo_skyrockblog_tiny.jpg b/assets/2007/6/3/logo_skyrockblog_tiny.jpg new file mode 100644 index 000000000..26c985e7d Binary files /dev/null and b/assets/2007/6/3/logo_skyrockblog_tiny.jpg differ diff --git a/assets/2007/6/3/logo_thumb.gif b/assets/2007/6/3/logo_thumb.gif new file mode 100644 index 000000000..ca542a13a Binary files /dev/null and b/assets/2007/6/3/logo_thumb.gif differ diff --git a/assets/2007/6/3/logo_thumb.png b/assets/2007/6/3/logo_thumb.png new file mode 100644 index 000000000..ae5585a93 Binary files /dev/null and b/assets/2007/6/3/logo_thumb.png differ diff --git a/assets/2007/6/3/logo_tiny.gif b/assets/2007/6/3/logo_tiny.gif new file mode 100644 index 000000000..664737c14 Binary files /dev/null and b/assets/2007/6/3/logo_tiny.gif differ diff --git a/assets/2007/6/3/logo_tiny.png b/assets/2007/6/3/logo_tiny.png new file mode 100644 index 000000000..6e2638f84 Binary files /dev/null and b/assets/2007/6/3/logo_tiny.png differ diff --git a/assets/2007/6/3/logo_xing_top.gif b/assets/2007/6/3/logo_xing_top.gif new file mode 100644 index 000000000..08675bab2 Binary files /dev/null and b/assets/2007/6/3/logo_xing_top.gif differ diff --git a/assets/2007/6/3/logo_xing_top_thumb.gif b/assets/2007/6/3/logo_xing_top_thumb.gif new file mode 100644 index 000000000..894691299 Binary files /dev/null and b/assets/2007/6/3/logo_xing_top_thumb.gif differ diff --git a/assets/2007/6/3/logo_xing_top_tiny.gif b/assets/2007/6/3/logo_xing_top_tiny.gif new file mode 100644 index 000000000..ed3225027 Binary files /dev/null and b/assets/2007/6/3/logo_xing_top_tiny.gif differ diff --git a/assets/2007/6/3/mapquest.jpg b/assets/2007/6/3/mapquest.jpg new file mode 100644 index 000000000..30419004d Binary files /dev/null and b/assets/2007/6/3/mapquest.jpg differ diff --git a/assets/2007/6/3/mapquest_thumb.jpg b/assets/2007/6/3/mapquest_thumb.jpg new file mode 100644 index 000000000..b5db4a89d Binary files /dev/null and b/assets/2007/6/3/mapquest_thumb.jpg differ diff --git a/assets/2007/6/3/mapquest_tiny.jpg b/assets/2007/6/3/mapquest_tiny.jpg new file mode 100644 index 000000000..0ff98ae95 Binary files /dev/null and b/assets/2007/6/3/mapquest_tiny.jpg differ diff --git a/assets/2007/6/3/mingle2.jpg b/assets/2007/6/3/mingle2.jpg new file mode 100644 index 000000000..29c3c1a75 Binary files /dev/null and b/assets/2007/6/3/mingle2.jpg differ diff --git a/assets/2007/6/3/mingle2_thumb.jpg b/assets/2007/6/3/mingle2_thumb.jpg new file mode 100644 index 000000000..009620cb0 Binary files /dev/null and b/assets/2007/6/3/mingle2_thumb.jpg differ diff --git a/assets/2007/6/3/mingle2_tiny.jpg b/assets/2007/6/3/mingle2_tiny.jpg new file mode 100644 index 000000000..bb66319bc Binary files /dev/null and b/assets/2007/6/3/mingle2_tiny.jpg differ diff --git a/assets/2007/6/3/odeo.gif b/assets/2007/6/3/odeo.gif new file mode 100644 index 000000000..71c9ce056 Binary files /dev/null and b/assets/2007/6/3/odeo.gif differ diff --git a/assets/2007/6/3/odeo_thumb.gif b/assets/2007/6/3/odeo_thumb.gif new file mode 100644 index 000000000..5dc905ba8 Binary files /dev/null and b/assets/2007/6/3/odeo_thumb.gif differ diff --git a/assets/2007/6/3/odeo_tiny.gif b/assets/2007/6/3/odeo_tiny.gif new file mode 100644 index 000000000..d4162ee1e Binary files /dev/null and b/assets/2007/6/3/odeo_tiny.gif differ diff --git a/assets/2007/6/3/oscar_1.gif b/assets/2007/6/3/oscar_1.gif new file mode 100644 index 000000000..7d571362a Binary files /dev/null and b/assets/2007/6/3/oscar_1.gif differ diff --git a/assets/2007/6/3/oscar_1_thumb.gif b/assets/2007/6/3/oscar_1_thumb.gif new file mode 100644 index 000000000..19ad88a03 Binary files /dev/null and b/assets/2007/6/3/oscar_1_thumb.gif differ diff --git a/assets/2007/6/3/oscar_1_tiny.gif b/assets/2007/6/3/oscar_1_tiny.gif new file mode 100644 index 000000000..02bb4d02c Binary files /dev/null and b/assets/2007/6/3/oscar_1_tiny.gif differ diff --git a/assets/2007/6/3/reddit.com.header.png b/assets/2007/6/3/reddit.com.header.png new file mode 100644 index 000000000..44e7c5c8b Binary files /dev/null and b/assets/2007/6/3/reddit.com.header.png differ diff --git a/assets/2007/6/3/reddit.com.header_thumb.png b/assets/2007/6/3/reddit.com.header_thumb.png new file mode 100644 index 000000000..ac80a7a40 Binary files /dev/null and b/assets/2007/6/3/reddit.com.header_thumb.png differ diff --git a/assets/2007/6/3/reddit.com.header_tiny.png b/assets/2007/6/3/reddit.com.header_tiny.png new file mode 100644 index 000000000..52a4786bd Binary files /dev/null and b/assets/2007/6/3/reddit.com.header_tiny.png differ diff --git a/assets/2007/6/3/revver-logo.gif b/assets/2007/6/3/revver-logo.gif new file mode 100644 index 000000000..44095a27c Binary files /dev/null and b/assets/2007/6/3/revver-logo.gif differ diff --git a/assets/2007/6/3/revver-logo_thumb.gif b/assets/2007/6/3/revver-logo_thumb.gif new file mode 100644 index 000000000..a11580a92 Binary files /dev/null and b/assets/2007/6/3/revver-logo_thumb.gif differ diff --git a/assets/2007/6/3/revver-logo_tiny.gif b/assets/2007/6/3/revver-logo_tiny.gif new file mode 100644 index 000000000..72df695c1 Binary files /dev/null and b/assets/2007/6/3/revver-logo_tiny.gif differ diff --git a/assets/2007/6/3/tupalo.gif b/assets/2007/6/3/tupalo.gif new file mode 100644 index 000000000..eafa82909 Binary files /dev/null and b/assets/2007/6/3/tupalo.gif differ diff --git a/assets/2007/6/3/tupalo_thumb.gif b/assets/2007/6/3/tupalo_thumb.gif new file mode 100644 index 000000000..a9df45ccd Binary files /dev/null and b/assets/2007/6/3/tupalo_thumb.gif differ diff --git a/assets/2007/6/3/tupalo_tiny.gif b/assets/2007/6/3/tupalo_tiny.gif new file mode 100644 index 000000000..d82ebebea Binary files /dev/null and b/assets/2007/6/3/tupalo_tiny.gif differ diff --git a/assets/2007/6/3/usa-today.gif b/assets/2007/6/3/usa-today.gif new file mode 100644 index 000000000..5444dfaaa Binary files /dev/null and b/assets/2007/6/3/usa-today.gif differ diff --git a/assets/2007/6/3/usa-today_1.gif b/assets/2007/6/3/usa-today_1.gif new file mode 100644 index 000000000..a7e90ea4f Binary files /dev/null and b/assets/2007/6/3/usa-today_1.gif differ diff --git a/assets/2007/6/3/usa-today_1_thumb.gif b/assets/2007/6/3/usa-today_1_thumb.gif new file mode 100644 index 000000000..ba089ecae Binary files /dev/null and b/assets/2007/6/3/usa-today_1_thumb.gif differ diff --git a/assets/2007/6/3/usa-today_1_tiny.gif b/assets/2007/6/3/usa-today_1_tiny.gif new file mode 100644 index 000000000..4c8c63c1e Binary files /dev/null and b/assets/2007/6/3/usa-today_1_tiny.gif differ diff --git a/assets/2007/6/3/usa-today_thumb.gif b/assets/2007/6/3/usa-today_thumb.gif new file mode 100644 index 000000000..b5dc76cd1 Binary files /dev/null and b/assets/2007/6/3/usa-today_thumb.gif differ diff --git a/assets/2007/6/3/usa-today_tiny.gif b/assets/2007/6/3/usa-today_tiny.gif new file mode 100644 index 000000000..669cc37d5 Binary files /dev/null and b/assets/2007/6/3/usa-today_tiny.gif differ diff --git a/assets/2007/6/3/usatoday.gif b/assets/2007/6/3/usatoday.gif new file mode 100644 index 000000000..01826b215 Binary files /dev/null and b/assets/2007/6/3/usatoday.gif differ diff --git a/assets/2007/6/3/usatoday_thumb.gif b/assets/2007/6/3/usatoday_thumb.gif new file mode 100644 index 000000000..0defa5687 Binary files /dev/null and b/assets/2007/6/3/usatoday_thumb.gif differ diff --git a/assets/2007/6/3/usatoday_tiny.gif b/assets/2007/6/3/usatoday_tiny.gif new file mode 100644 index 000000000..6de9fb0ab Binary files /dev/null and b/assets/2007/6/3/usatoday_tiny.gif differ diff --git a/assets/2007/6/3/weewar_logo_white.gif b/assets/2007/6/3/weewar_logo_white.gif new file mode 100644 index 000000000..14853346a Binary files /dev/null and b/assets/2007/6/3/weewar_logo_white.gif differ diff --git a/assets/2007/6/3/weewar_logo_white_thumb.gif b/assets/2007/6/3/weewar_logo_white_thumb.gif new file mode 100644 index 000000000..69d1af9e1 Binary files /dev/null and b/assets/2007/6/3/weewar_logo_white_thumb.gif differ diff --git a/assets/2007/6/3/weewar_logo_white_tiny.gif b/assets/2007/6/3/weewar_logo_white_tiny.gif new file mode 100644 index 000000000..c1e1ab227 Binary files /dev/null and b/assets/2007/6/3/weewar_logo_white_tiny.gif differ diff --git a/assets/2007/6/3/xangalogosmall.gif b/assets/2007/6/3/xangalogosmall.gif new file mode 100644 index 000000000..65e4003fe Binary files /dev/null and b/assets/2007/6/3/xangalogosmall.gif differ diff --git a/assets/2007/6/3/xangalogosmall_thumb.gif b/assets/2007/6/3/xangalogosmall_thumb.gif new file mode 100644 index 000000000..e479bf503 Binary files /dev/null and b/assets/2007/6/3/xangalogosmall_thumb.gif differ diff --git a/assets/2007/6/3/xangalogosmall_tiny.gif b/assets/2007/6/3/xangalogosmall_tiny.gif new file mode 100644 index 000000000..c87a54335 Binary files /dev/null and b/assets/2007/6/3/xangalogosmall_tiny.gif differ diff --git a/assets/2007/6/3/yelp.gif b/assets/2007/6/3/yelp.gif new file mode 100644 index 000000000..043329de5 Binary files /dev/null and b/assets/2007/6/3/yelp.gif differ diff --git a/assets/2007/6/3/yelp_thumb.gif b/assets/2007/6/3/yelp_thumb.gif new file mode 100644 index 000000000..079d22d1a Binary files /dev/null and b/assets/2007/6/3/yelp_thumb.gif differ diff --git a/assets/2007/6/3/yelp_tiny.gif b/assets/2007/6/3/yelp_tiny.gif new file mode 100644 index 000000000..19488ba40 Binary files /dev/null and b/assets/2007/6/3/yelp_tiny.gif differ diff --git a/assets/2007/6/4/dropsendlogo.gif b/assets/2007/6/4/dropsendlogo.gif new file mode 100644 index 000000000..ad9f7a0a4 Binary files /dev/null and b/assets/2007/6/4/dropsendlogo.gif differ diff --git a/assets/2007/6/4/dropsendlogo_thumb.gif b/assets/2007/6/4/dropsendlogo_thumb.gif new file mode 100644 index 000000000..1ba555eea Binary files /dev/null and b/assets/2007/6/4/dropsendlogo_thumb.gif differ diff --git a/assets/2007/6/4/dropsendlogo_tiny.gif b/assets/2007/6/4/dropsendlogo_tiny.gif new file mode 100644 index 000000000..81f726cae Binary files /dev/null and b/assets/2007/6/4/dropsendlogo_tiny.gif differ diff --git a/assets/2007/6/4/fifa.com.gif b/assets/2007/6/4/fifa.com.gif new file mode 100644 index 000000000..f63fb5471 Binary files /dev/null and b/assets/2007/6/4/fifa.com.gif differ diff --git a/assets/2007/6/4/fifa.com_thumb.gif b/assets/2007/6/4/fifa.com_thumb.gif new file mode 100644 index 000000000..4bebbfd3f Binary files /dev/null and b/assets/2007/6/4/fifa.com_thumb.gif differ diff --git a/assets/2007/6/4/fifa.com_tiny.gif b/assets/2007/6/4/fifa.com_tiny.gif new file mode 100644 index 000000000..dbc254d6d Binary files /dev/null and b/assets/2007/6/4/fifa.com_tiny.gif differ diff --git a/assets/2007/6/4/hm_logo_print.gif b/assets/2007/6/4/hm_logo_print.gif new file mode 100644 index 000000000..29f06dcaf Binary files /dev/null and b/assets/2007/6/4/hm_logo_print.gif differ diff --git a/assets/2007/6/4/hm_logo_print_thumb.gif b/assets/2007/6/4/hm_logo_print_thumb.gif new file mode 100644 index 000000000..21d74e4c4 Binary files /dev/null and b/assets/2007/6/4/hm_logo_print_thumb.gif differ diff --git a/assets/2007/6/4/hm_logo_print_tiny.gif b/assets/2007/6/4/hm_logo_print_tiny.gif new file mode 100644 index 000000000..e1d862cb4 Binary files /dev/null and b/assets/2007/6/4/hm_logo_print_tiny.gif differ diff --git a/assets/2007/6/4/justin.jpg b/assets/2007/6/4/justin.jpg new file mode 100644 index 000000000..94ec6cec5 Binary files /dev/null and b/assets/2007/6/4/justin.jpg differ diff --git a/assets/2007/6/4/justin_1.jpg b/assets/2007/6/4/justin_1.jpg new file mode 100644 index 000000000..f578b8bc6 Binary files /dev/null and b/assets/2007/6/4/justin_1.jpg differ diff --git a/assets/2007/6/4/justin_1_thumb.jpg b/assets/2007/6/4/justin_1_thumb.jpg new file mode 100644 index 000000000..43055ceb8 Binary files /dev/null and b/assets/2007/6/4/justin_1_thumb.jpg differ diff --git a/assets/2007/6/4/justin_1_tiny.jpg b/assets/2007/6/4/justin_1_tiny.jpg new file mode 100644 index 000000000..41565ffa9 Binary files /dev/null and b/assets/2007/6/4/justin_1_tiny.jpg differ diff --git a/assets/2007/6/4/justin_thumb.jpg b/assets/2007/6/4/justin_thumb.jpg new file mode 100644 index 000000000..3658cf04c Binary files /dev/null and b/assets/2007/6/4/justin_thumb.jpg differ diff --git a/assets/2007/6/4/justin_tiny.jpg b/assets/2007/6/4/justin_tiny.jpg new file mode 100644 index 000000000..581001092 Binary files /dev/null and b/assets/2007/6/4/justin_tiny.jpg differ diff --git a/assets/2007/6/4/logo.gif b/assets/2007/6/4/logo.gif new file mode 100644 index 000000000..ebb1024ec Binary files /dev/null and b/assets/2007/6/4/logo.gif differ diff --git a/assets/2007/6/4/logo_1.gif b/assets/2007/6/4/logo_1.gif new file mode 100644 index 000000000..860f36816 Binary files /dev/null and b/assets/2007/6/4/logo_1.gif differ diff --git a/assets/2007/6/4/logo_1_thumb.gif b/assets/2007/6/4/logo_1_thumb.gif new file mode 100644 index 000000000..71a9a32b6 Binary files /dev/null and b/assets/2007/6/4/logo_1_thumb.gif differ diff --git a/assets/2007/6/4/logo_1_tiny.gif b/assets/2007/6/4/logo_1_tiny.gif new file mode 100644 index 000000000..471ea1376 Binary files /dev/null and b/assets/2007/6/4/logo_1_tiny.gif differ diff --git a/assets/2007/6/4/logo_2.gif b/assets/2007/6/4/logo_2.gif new file mode 100644 index 000000000..33216d5c2 Binary files /dev/null and b/assets/2007/6/4/logo_2.gif differ diff --git a/assets/2007/6/4/logo_2_thumb.gif b/assets/2007/6/4/logo_2_thumb.gif new file mode 100644 index 000000000..d6337b02c Binary files /dev/null and b/assets/2007/6/4/logo_2_thumb.gif differ diff --git a/assets/2007/6/4/logo_2_tiny.gif b/assets/2007/6/4/logo_2_tiny.gif new file mode 100644 index 000000000..3f6dd97ea Binary files /dev/null and b/assets/2007/6/4/logo_2_tiny.gif differ diff --git a/assets/2007/6/4/logo_small.gif b/assets/2007/6/4/logo_small.gif new file mode 100644 index 000000000..840ce0444 Binary files /dev/null and b/assets/2007/6/4/logo_small.gif differ diff --git a/assets/2007/6/4/logo_small_thumb.gif b/assets/2007/6/4/logo_small_thumb.gif new file mode 100644 index 000000000..ca3b3a86f Binary files /dev/null and b/assets/2007/6/4/logo_small_thumb.gif differ diff --git a/assets/2007/6/4/logo_small_tiny.gif b/assets/2007/6/4/logo_small_tiny.gif new file mode 100644 index 000000000..695ee6e5b Binary files /dev/null and b/assets/2007/6/4/logo_small_tiny.gif differ diff --git a/assets/2007/6/4/logo_sony.gif b/assets/2007/6/4/logo_sony.gif new file mode 100644 index 000000000..4a5c8f1f6 Binary files /dev/null and b/assets/2007/6/4/logo_sony.gif differ diff --git a/assets/2007/6/4/logo_sony_thumb.gif b/assets/2007/6/4/logo_sony_thumb.gif new file mode 100644 index 000000000..b83c9e18f Binary files /dev/null and b/assets/2007/6/4/logo_sony_thumb.gif differ diff --git a/assets/2007/6/4/logo_sony_tiny.gif b/assets/2007/6/4/logo_sony_tiny.gif new file mode 100644 index 000000000..3521d5a0e Binary files /dev/null and b/assets/2007/6/4/logo_sony_tiny.gif differ diff --git a/assets/2007/6/4/logo_swsoft.gif b/assets/2007/6/4/logo_swsoft.gif new file mode 100644 index 000000000..920c67277 Binary files /dev/null and b/assets/2007/6/4/logo_swsoft.gif differ diff --git a/assets/2007/6/4/logo_swsoft_thumb.gif b/assets/2007/6/4/logo_swsoft_thumb.gif new file mode 100644 index 000000000..ab2a90402 Binary files /dev/null and b/assets/2007/6/4/logo_swsoft_thumb.gif differ diff --git a/assets/2007/6/4/logo_swsoft_tiny.gif b/assets/2007/6/4/logo_swsoft_tiny.gif new file mode 100644 index 000000000..fa3831333 Binary files /dev/null and b/assets/2007/6/4/logo_swsoft_tiny.gif differ diff --git a/assets/2007/6/4/logo_thumb.gif b/assets/2007/6/4/logo_thumb.gif new file mode 100644 index 000000000..94d744b79 Binary files /dev/null and b/assets/2007/6/4/logo_thumb.gif differ diff --git a/assets/2007/6/4/logo_tiny.gif b/assets/2007/6/4/logo_tiny.gif new file mode 100644 index 000000000..2c1cea4b5 Binary files /dev/null and b/assets/2007/6/4/logo_tiny.gif differ diff --git a/assets/2007/6/4/mission.gif b/assets/2007/6/4/mission.gif new file mode 100644 index 000000000..97356600c Binary files /dev/null and b/assets/2007/6/4/mission.gif differ diff --git a/assets/2007/6/4/mission_thumb.gif b/assets/2007/6/4/mission_thumb.gif new file mode 100644 index 000000000..6dbc1ae2c Binary files /dev/null and b/assets/2007/6/4/mission_thumb.gif differ diff --git a/assets/2007/6/4/mission_tiny.gif b/assets/2007/6/4/mission_tiny.gif new file mode 100644 index 000000000..b1ebefc83 Binary files /dev/null and b/assets/2007/6/4/mission_tiny.gif differ diff --git a/assets/2007/6/4/prada_logo_print.gif b/assets/2007/6/4/prada_logo_print.gif new file mode 100644 index 000000000..1dbd31f53 Binary files /dev/null and b/assets/2007/6/4/prada_logo_print.gif differ diff --git a/assets/2007/6/4/prada_logo_print_thumb.gif b/assets/2007/6/4/prada_logo_print_thumb.gif new file mode 100644 index 000000000..5f6f15e31 Binary files /dev/null and b/assets/2007/6/4/prada_logo_print_thumb.gif differ diff --git a/assets/2007/6/4/prada_logo_print_tiny.gif b/assets/2007/6/4/prada_logo_print_tiny.gif new file mode 100644 index 000000000..56c100f4b Binary files /dev/null and b/assets/2007/6/4/prada_logo_print_tiny.gif differ diff --git a/assets/2007/6/4/wired_logo.gif b/assets/2007/6/4/wired_logo.gif new file mode 100644 index 000000000..8a69f5ea2 Binary files /dev/null and b/assets/2007/6/4/wired_logo.gif differ diff --git a/assets/2007/6/4/wired_logo_1.gif b/assets/2007/6/4/wired_logo_1.gif new file mode 100644 index 000000000..3c6c51895 Binary files /dev/null and b/assets/2007/6/4/wired_logo_1.gif differ diff --git a/assets/2007/6/4/wired_logo_1_thumb.gif b/assets/2007/6/4/wired_logo_1_thumb.gif new file mode 100644 index 000000000..96e25d2f1 Binary files /dev/null and b/assets/2007/6/4/wired_logo_1_thumb.gif differ diff --git a/assets/2007/6/4/wired_logo_1_tiny.gif b/assets/2007/6/4/wired_logo_1_tiny.gif new file mode 100644 index 000000000..3717be078 Binary files /dev/null and b/assets/2007/6/4/wired_logo_1_tiny.gif differ diff --git a/assets/2007/6/4/wired_logo_thumb.gif b/assets/2007/6/4/wired_logo_thumb.gif new file mode 100644 index 000000000..94f0648d6 Binary files /dev/null and b/assets/2007/6/4/wired_logo_thumb.gif differ diff --git a/assets/2007/6/4/wired_logo_tiny.gif b/assets/2007/6/4/wired_logo_tiny.gif new file mode 100644 index 000000000..596a655a7 Binary files /dev/null and b/assets/2007/6/4/wired_logo_tiny.gif differ diff --git a/assets/2007/6/4/zooomr_fresh_logo_sm_mk3.png b/assets/2007/6/4/zooomr_fresh_logo_sm_mk3.png new file mode 100644 index 000000000..fe27ac6d7 Binary files /dev/null and b/assets/2007/6/4/zooomr_fresh_logo_sm_mk3.png differ diff --git a/assets/2007/6/4/zooomr_fresh_logo_sm_mk3_thumb.png b/assets/2007/6/4/zooomr_fresh_logo_sm_mk3_thumb.png new file mode 100644 index 000000000..bf1d2cd1e Binary files /dev/null and b/assets/2007/6/4/zooomr_fresh_logo_sm_mk3_thumb.png differ diff --git a/assets/2007/6/4/zooomr_fresh_logo_sm_mk3_tiny.png b/assets/2007/6/4/zooomr_fresh_logo_sm_mk3_tiny.png new file mode 100644 index 000000000..b4858e840 Binary files /dev/null and b/assets/2007/6/4/zooomr_fresh_logo_sm_mk3_tiny.png differ diff --git a/assets/2007/6/5/header_cnn_com_logo.gif b/assets/2007/6/5/header_cnn_com_logo.gif new file mode 100644 index 000000000..839cc640a Binary files /dev/null and b/assets/2007/6/5/header_cnn_com_logo.gif differ diff --git a/assets/2007/6/5/header_cnn_com_logo_thumb.gif b/assets/2007/6/5/header_cnn_com_logo_thumb.gif new file mode 100644 index 000000000..77410e512 Binary files /dev/null and b/assets/2007/6/5/header_cnn_com_logo_thumb.gif differ diff --git a/assets/2007/6/5/header_cnn_com_logo_tiny.gif b/assets/2007/6/5/header_cnn_com_logo_tiny.gif new file mode 100644 index 000000000..d0782fabf Binary files /dev/null and b/assets/2007/6/5/header_cnn_com_logo_tiny.gif differ diff --git a/assets/2007/7/31/Seth.jpg b/assets/2007/7/31/Seth.jpg new file mode 100644 index 000000000..e394c5997 Binary files /dev/null and b/assets/2007/7/31/Seth.jpg differ diff --git a/assets/2007/7/31/Seth_thumb.jpg b/assets/2007/7/31/Seth_thumb.jpg new file mode 100644 index 000000000..2cdc28b88 Binary files /dev/null and b/assets/2007/7/31/Seth_thumb.jpg differ diff --git a/assets/2007/7/31/Seth_tiny.jpg b/assets/2007/7/31/Seth_tiny.jpg new file mode 100644 index 000000000..eb9851c2e Binary files /dev/null and b/assets/2007/7/31/Seth_tiny.jpg differ diff --git a/assets/2007/7/9/header_cnn_com_logo.gif b/assets/2007/7/9/header_cnn_com_logo.gif new file mode 100644 index 000000000..db60975c0 Binary files /dev/null and b/assets/2007/7/9/header_cnn_com_logo.gif differ diff --git a/assets/2007/7/9/header_cnn_com_logo_thumb.gif b/assets/2007/7/9/header_cnn_com_logo_thumb.gif new file mode 100644 index 000000000..476b4f060 Binary files /dev/null and b/assets/2007/7/9/header_cnn_com_logo_thumb.gif differ diff --git a/assets/2007/7/9/header_cnn_com_logo_tiny.gif b/assets/2007/7/9/header_cnn_com_logo_tiny.gif new file mode 100644 index 000000000..3f49ad9d5 Binary files /dev/null and b/assets/2007/7/9/header_cnn_com_logo_tiny.gif differ diff --git a/assets/2007/8/15/prototype.js b/assets/2007/8/15/prototype.js new file mode 100644 index 000000000..e85c94c5a --- /dev/null +++ b/assets/2007/8/15/prototype.js @@ -0,0 +1,4174 @@ +/* Prototype JavaScript framework, version 1.6.0_rc0 + * (c) 2005-2007 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.6.0_rc0', + + Browser: { + IE: !!(window.attachEvent && !window.opera), + Opera: !!window.opera, + WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1, + Gecko: navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1, + MobileSafari: !!navigator.userAgent.match(/iPhone.*Mobile.*Safari/) + }, + + BrowserFeatures: { + XPath: !!document.evaluate, + ElementExtensions: !!window.HTMLElement, + SpecificElementExtensions: + document.createElement('div').__proto__ !== + document.createElement('form').__proto__ + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + +/* Based on Alex Arnell's inheritance implementation. */ +var Class = { + create: function(parent, methods) { + if (arguments.length == 1 && !Object.isFunction(parent)) + methods = parent, parent = null; + + var method = function() { + if (!Class.extending) this.initialize.apply(this, arguments); + }; + + method.superclass = parent; + method.subclasses = []; + + if (Object.isFunction(parent)) { + Class.extending = true; + method.prototype = new parent(); + + parent.subclasses.push(method); + + delete Class.extending; + } + + if (methods) Class.extend(method, methods); + method.prototype.constructor = method; + + return method; + }, + + extend: function(destination, source) { + for (var name in source) Class.inherit(destination, source, name); + return destination; + }, + + inherit: function(destination, source, name) { + var prototype = destination.prototype, ancestor = prototype[name], + descendant = source[name]; + if (ancestor && Object.isFunction(descendant) && + descendant.argumentNames().first() == "$super") { + var method = descendant, descendant = ancestor.wrap(method); + Object.extend(descendant, { + valueOf: function() { return method }, + toString: function() { return method.toString() } + }); + } + + prototype[name] = descendant; + + if (destination.subclasses && destination.subclasses.length > 0) { + for (var i = 0, subclass; subclass = destination.subclasses[i]; i++) { + Class.extending = true; + Object.extend(subclass.prototype, new destination()); + subclass.prototype.constructor = subclass; + delete Class.extending; + Class.inherit(subclass, destination.prototype, name); + } + } + }, + + mixin: function(destination, source) { + return Object.extend(destination, source); + } +}; + +var Abstract = { }; + +Object.extend = function(destination, source) { + for (var property in source) { + destination[property] = source[property]; + } + return destination; +}; + +Object.extend(Object, { + inspect: function(object) { + try { + if (object === undefined) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : object.toString(); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + }, + + toJSON: function(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (Object.isElement(object)) return; + + var results = []; + for (var property in object) { + var value = Object.toJSON(object[property]); + if (value !== undefined) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + }, + + toHTML: function(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + }, + + keys: function(object) { + var keys = []; + for (var property in object) + keys.push(property); + return keys; + }, + + values: function(object) { + var values = []; + for (var property in object) + values.push(object[property]); + return values; + }, + + clone: function(object) { + return Object.extend({ }, object); + }, + + isElement: function(object) { + return object && object.nodeType == 1; + }, + + isArray: function(object) { + return object && object.constructor === Array; + }, + + isFunction: function(object) { + return typeof object == "function"; + }, + + isString: function(object) { + return typeof object == "string"; + }, + + isNumber: function(object) { + return typeof object == "number"; + }, + + isUndefined: function(object) { + return typeof object == "undefined"; + } +}); + +Object.extend(Function.prototype, { + argumentNames: function() { + var names = this.toString().match(/^[\s\(]*function\s*\((.*?)\)/)[1].split(",").invoke("strip"); + return names.length == 1 && !names[0] ? [] : names; + }, + + bind: function() { + if (arguments.length < 2 && arguments[0] === undefined) return this; + var __method = this, args = $A(arguments), object = args.shift(); + return function() { + return __method.apply(object, args.concat($A(arguments))); + } + }, + + bindAsEventListener: function() { + var __method = this, args = $A(arguments), object = args.shift(); + return function(event) { + return __method.apply(object, [event || window.event].concat(args)); + } + }, + + curry: function() { + if (!arguments.length) return this; + var __method = this, args = $A(arguments); + return function() { + return __method.apply(this, args.concat($A(arguments))); + } + }, + + delay: function() { + var __method = this, args = $A(arguments), timeout = args.shift() * 1000; + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + }, + + wrap: function(wrapper) { + var __method = this; + return function() { + return wrapper.apply(this, [__method.bind(this)].concat($A(arguments))); + } + }, + + methodize: function() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + return __method.apply(null, [this].concat($A(arguments))); + }; + } +}); + +Function.prototype.defer = Function.prototype.delay.curry(0.01); + +Date.prototype.toJSON = function() { + return '"' + this.getFullYear() + '-' + + (this.getMonth() + 1).toPaddedString(2) + '-' + + this.getDate().toPaddedString(2) + 'T' + + this.getHours().toPaddedString(2) + ':' + + this.getMinutes().toPaddedString(2) + ':' + + this.getSeconds().toPaddedString(2) + '"'; +}; + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; + +/*--------------------------------------------------------------------------*/ + +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.callback(this); + } finally { + this.currentlyExecuting = false; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, { + gsub: function(pattern, replacement) { + var result = '', source = this, match; + replacement = arguments.callee.prepareReplacement(replacement); + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + }, + + sub: function(pattern, replacement, count) { + replacement = this.gsub.prepareReplacement(replacement); + count = count === undefined ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + }, + + scan: function(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + }, + + truncate: function(length, truncation) { + length = length || 30; + truncation = truncation === undefined ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + }, + + strip: function() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + }, + + stripTags: function() { + return this.replace(/<\/?[^>]+>/gi, ''); + }, + + stripScripts: function() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + }, + + extractScripts: function() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + }, + + evalScripts: function() { + return this.extractScripts().map(function(script) { return eval(script) }); + }, + + escapeHTML: function() { + var self = arguments.callee; + self.text.data = this; + return self.div.innerHTML; + }, + + unescapeHTML: function() { + var div = new Element('div'); + div.innerHTML = this.stripTags(); + return div.childNodes[0] ? (div.childNodes.length > 1 ? + $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) : + div.childNodes[0].nodeValue) : ''; + }, + + toQueryParams: function(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + }, + + toArray: function() { + return this.split(''); + }, + + succ: function() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + }, + + times: function(count) { + var result = ''; + for (var i = 0; i < count; i++) result += this; + return result; + }, + + camelize: function() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + }, + + capitalize: function() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + }, + + underscore: function() { + return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase(); + }, + + dasherize: function() { + return this.gsub(/_/,'-'); + }, + + inspect: function(useDoubleQuotes) { + var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) { + var character = String.specialChar[match[0]]; + return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + }, + + toJSON: function() { + return this.inspect(true); + }, + + unfilterJSON: function(filter) { + return this.sub(filter || Prototype.JSONFilter, '#{1}'); + }, + + isJSON: function() { + var str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + }, + + evalJSON: function(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + }, + + include: function(pattern) { + return this.indexOf(pattern) > -1; + }, + + startsWith: function(pattern) { + return this.indexOf(pattern) === 0; + }, + + endsWith: function(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + }, + + empty: function() { + return this == ''; + }, + + blank: function() { + return /^\s*$/.test(this); + }, + + interpolate: function(object, pattern) { + return new Template(this, pattern).evaluate(object); + } +}); + +if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, { + escapeHTML: function() { + return this.replace(/&/g,'&').replace(//g,'>'); + }, + unescapeHTML: function() { + return this.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>'); + } +}); + +String.prototype.gsub.prepareReplacement = function(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; +}; + +String.prototype.parseQuery = String.prototype.toQueryParams; + +Object.extend(String.prototype.escapeHTML, { + div: document.createElement('div'), + text: document.createTextNode('') +}); + +with (String.prototype.escapeHTML) div.appendChild(text); + +var Template = Class.create(); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; +Template.prototype = { + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return ''; + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/, match = pattern.exec(expr); + if (match == null) return ''; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }.bind(this)); + } +}; + +var $break = { }; + +var Enumerable = { + each: function(iterator, context) { + var index = 0; + iterator = iterator.bind(context); + try { + this._each(function(value) { + iterator(value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + }, + + eachSlice: function(number, iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var index = -number, slices = [], array = this.toArray(); + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + }, + + all: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator(value, index); + if (!result) throw $break; + }); + return result; + }, + + any: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator(value, index)) + throw $break; + }); + return result; + }, + + collect: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator(value, index)); + }); + return results; + }, + + detect: function(iterator, context) { + iterator = iterator.bind(context); + var result; + this.each(function(value, index) { + if (iterator(value, index)) { + result = value; + throw $break; + } + }); + return result; + }, + + findAll: function(iterator, context) { + iterator = iterator.bind(context); + var results = []; + this.each(function(value, index) { + if (iterator(value, index)) + results.push(value); + }); + return results; + }, + + grep: function(filter, iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(filter); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator(value, index)); + }); + return results; + }, + + include: function(object) { + if (Object.isFunction(this.indexOf)) + return this.indexOf(object) != -1; + + var found = false; + this.each(function(value) { + if (value === object) { + found = true; + throw $break; + } + }); + return found; + }, + + inGroupsOf: function(number, fillWith) { + fillWith = fillWith === undefined ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + }, + + inject: function(memo, iterator, context) { + iterator = iterator.bind(context); + this.each(function(value, index) { + memo = iterator(memo, value, index); + }); + return memo; + }, + + invoke: function(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + }, + + max: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result; + this.each(function(value, index) { + value = iterator(value, index); + if (result == undefined || value >= result) + result = value; + }); + return result; + }, + + min: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var result; + this.each(function(value, index) { + value = iterator(value, index); + if (result == undefined || value < result) + result = value; + }); + return result; + }, + + partition: function(iterator, context) { + iterator = iterator ? iterator.bind(context) : Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator(value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + }, + + pluck: function(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + }, + + reject: function(iterator, context) { + iterator = iterator.bind(context); + var results = []; + this.each(function(value, index) { + if (!iterator(value, index)) + results.push(value); + }); + return results; + }, + + sortBy: function(iterator, context) { + iterator = iterator.bind(context); + return this.map(function(value, index) { + return {value: value, criteria: iterator(value, index)}; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + }, + + toArray: function() { + return this.map(); + }, + + zip: function() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + }, + + size: function() { + return this.toArray().length; + }, + + inspect: function() { + return '#'; + } +}; + +Object.extend(Enumerable, { + map: Enumerable.collect, + find: Enumerable.detect, + select: Enumerable.findAll, + filter: Enumerable.findAll, + member: Enumerable.include, + entries: Enumerable.toArray, + every: Enumerable.all, + some: Enumerable.any +}); +function $A(iterable) { + if (!iterable) return []; + if (iterable.toArray) return iterable.toArray(); + else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } +} + +if (Prototype.Browser.WebKit) { + function $A(iterable) { + if (!iterable) return []; + if (!(Object.isFunction(iterable) && iterable == '[object NodeList]') && + iterable.toArray) { + return iterable.toArray(); + } else { + var results = []; + for (var i = 0, length = iterable.length; i < length; i++) + results.push(iterable[i]); + return results; + } + } +} + +Array.from = $A; + +Object.extend(Array.prototype, Enumerable); + +if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse; + +Object.extend(Array.prototype, { + _each: function(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + }, + + clear: function() { + this.length = 0; + return this; + }, + + first: function() { + return this[0]; + }, + + last: function() { + return this[this.length - 1]; + }, + + compact: function() { + return this.select(function(value) { + return value != null; + }); + }, + + flatten: function() { + return this.inject([], function(array, value) { + return array.concat(Object.isArray(value) ? + value.flatten() : [value]); + }); + }, + + without: function() { + var values = $A(arguments); + return this.select(function(value) { + return !values.include(value); + }); + }, + + reverse: function(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + }, + + reduce: function() { + return this.length > 1 ? this : this[0]; + }, + + uniq: function(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + }, + + intersect: function(array) { + return this.uniq().findAll(function(item) { + return array.include(item); + }); + }, + + clone: function() { + return [].concat(this); + }, + + size: function() { + return this.length; + }, + + inspect: function() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + }, + + toJSON: function() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (value !== undefined) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } +}); + +// use native browser JS 1.6 implementation if available +if (Object.isFunction(Array.prototype.forEach)) + Array.prototype._each = Array.prototype.forEach; + +if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; +}; + +if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; +}; + +Array.prototype.toArray = Array.prototype.clone; + +function $w(string) { + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +if (Prototype.Browser.Opera){ + Array.prototype.concat = function() { + var array = []; + for (var i = 0, length = this.length; i < length; i++) array.push(this[i]); + for (var i = 0, length = arguments.length; i < length; i++) { + if (Object.isArray(arguments[i])) { + for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++) + array.push(arguments[i][j]); + } else { + array.push(arguments[i]); + } + } + return array; + }; +} +Object.extend(Number.prototype, { + toColorPart: function() { + return this.toPaddedString(2, 16); + }, + + succ: function() { + return this + 1; + }, + + times: function(iterator) { + $R(0, this, true).each(iterator); + return this; + }, + + toPaddedString: function(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + }, + + toJSON: function() { + return isFinite(this) ? this.toString() : 'null'; + } +}); + +$w('abs round ceil floor').each(function(method){ + Number.prototype[method] = Math[method].methodize(); +}); +var Hash = function(object) { + if (object instanceof Hash) this.merge(object); + else Object.extend(this, object || { }); +}; + +Object.extend(Hash, { + toQueryString: function(obj) { + var parts = []; + parts.add = arguments.callee.addPair; + + this.prototype._each.call(obj, function(pair) { + if (!pair.key) return; + var value = pair.value; + + if (value && typeof value == 'object') { + if (Object.isArray(value)) value.each(function(value) { + parts.add(pair.key, value); + }); + return; + } + parts.add(pair.key, value); + }); + + return parts.join('&'); + }, + + toJSON: function(object) { + var results = []; + this.prototype._each.call(object, function(pair) { + var value = Object.toJSON(pair.value); + if (value !== undefined) results.push(pair.key.toJSON() + ': ' + value); + }); + return '{' + results.join(', ') + '}'; + } +}); + +Hash.toQueryString.addPair = function(key, value, prefix) { + key = encodeURIComponent(key); + if (value === undefined) this.push(key); + else this.push(key + '=' + (value == null ? '' : encodeURIComponent(value))); +}; + +Object.extend(Hash.prototype, Enumerable); +Object.extend(Hash.prototype, { + _each: function(iterator) { + for (var key in this) { + var value = this[key]; + if (value && value == Hash.prototype[key]) continue; + + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + }, + + keys: function() { + return this.pluck('key'); + }, + + values: function() { + return this.pluck('value'); + }, + + index: function(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + }, + + merge: function(hash) { + return $H(hash).inject(this, function(mergedHash, pair) { + mergedHash[pair.key] = pair.value; + return mergedHash; + }); + }, + + remove: function() { + var result; + for(var i = 0, length = arguments.length; i < length; i++) { + var value = this[arguments[i]]; + if (value !== undefined){ + if (result === undefined) result = value; + else { + if (!Object.isArray(result)) result = [result]; + result.push(value); + } + } + delete this[arguments[i]]; + } + return result; + }, + + toQueryString: function() { + return Hash.toQueryString(this); + }, + + inspect: function() { + return '#'; + }, + + toJSON: function() { + return Hash.toJSON(this); + } +}); + +function $H(object) { + if (object instanceof Hash) return object; + return new Hash(object); +}; + +// Safari iterates over shadowed properties +if (function() { + var i = 0, Test = function(value) { this.key = value }; + Test.prototype.key = 'foo'; + for (var property in new Test('bar')) i++; + return i > 1; +}()) Hash.prototype._each = function(iterator) { + var cache = []; + for (var key in this) { + var value = this[key]; + if ((value && value == Hash.prototype[key]) || cache.include(key)) continue; + cache.push(key); + var pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } +}; +ObjectRange = Class.create(); +Object.extend(ObjectRange.prototype, Enumerable); +Object.extend(ObjectRange.prototype, { + initialize: function(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + }, + + _each: function(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + }, + + include: function(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } +}); + +var $R = function(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +}; + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { + Ajax.activeRequestCount++; + }, + onComplete: function() { + Ajax.activeRequestCount--; + } +}); + +Ajax.Base = function() { }; +Ajax.Base.prototype = { + setOptions: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + } +}; + +Ajax.Request = Class.create(); +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + +Ajax.Request.prototype = Object.extend(new Ajax.Base(), { + _complete: false, + + initialize: function(url, options) { + this.transport = Ajax.getTransport(); + this.setOptions(options); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + // simulate other verbs over post + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Hash.toQueryString(params)) { + // when GET, append parameters to URL + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + // user-defined headers + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + // avoid memory leak in MSIE: clean up + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name); + } catch (e) { return null } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Response = Class.create(); +Ajax.Response.prototype = { + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this.getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = xml === undefined ? null : xml; + this.responseJSON = this.getResponseJSON(); + } + }, + + status: 0, + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + try { + return json ? json.evalJSON(this.request.options.sanitizeJSON) : null; + } catch (e) { + this.request.dispatchException(e); + } + }, + + getResponseJSON: function() { + var options = this.request.options; + try { + if (options.evalJSON == 'force' || (options.evalJSON && + (this.getHeader('Content-type') || '').include('application/json'))) + return this.transport.responseText.evalJSON(options.sanitizeJSON); + return null; + } catch (e) { + this.request.dispatchException(e); + } + } +}; + +Ajax.Updater = Class.create(); + +Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { + initialize: function(container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + this.transport = Ajax.getTransport(); + this.setOptions(options); + + var onComplete = this.options.onComplete || Prototype.emptyFunction; + this.options.onComplete = (function(response, param) { + this.updateContent(response.responseText); + onComplete(response, param); + }).bind(this); + + this.request(url); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + + if (this.success()) { + if (this.onComplete) this.onComplete.bind(this).defer(); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(); +Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { + initialize: function(container, url, options) { + this.setOptions(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(responseText) { + if (this.options.decay) { + this.decay = (responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +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; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) + var Node = { }; + +Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 +}); + +(function() { + var element = this.Element; + this.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (Prototype.Browser.IE && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(this.Element, element || { }); +}).call(window); + +Element.cache = { }; + +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, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + content = Object.toHTML(content); + element.innerHTML = content.stripScripts(); + content.evalScripts.bind(content).defer(); + return element; + }, + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, t, range; + + for (position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + t = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + t.insert(element, content); + continue; + } + + content = Object.toHTML(content); + + range = element.ownerDocument.createRange(); + t.initializeRange(element, range); + t.insert(element, range.createContextualFragment(content.stripScripts())); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return element; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return $(element).recursivelyCollect('parentNode'); + }, + + descendants: function(element) { + return $A($(element).getElementsByTagName('*')).each(Element.extend); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return $(element).recursivelyCollect('previousSibling'); + }, + + nextSiblings: function(element) { + return $(element).recursivelyCollect('nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return element.previousSiblings().reverse().concat(element.nextSiblings()); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + 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]; + }, + + select: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element, args); + }, + + adjacent: function() { + var args = $A(arguments), element = $(args.shift()); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = element.readAttribute('id'), self = arguments.callee; + if (id) return id; + do { id = 'anonymous_element_' + self.counter++ } while ($(id)); + element.writeAttribute('id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = value === undefined ? true : value; + + for (var attr in attributes) { + var name = t.names[attr] || attr, value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return $(element).getDimensions().height; + }, + + getWidth: function(element) { + return $(element).getDimensions().width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + elementClassName.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!element.hasClassName(className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return element[element.hasClassName(className) ? + 'removeClassName' : 'addClassName'](className); + }, + + // 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + 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 = element.cumulativeOffset(); + 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) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (elementStyle.styleFloat === undefined ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + 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); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + 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; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p == 'relative' || p == 'absolute') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (element.getStyle('position') == 'absolute') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + var offsets = element.positionedOffset(); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (element.getStyle('position') == 'relative') return; + // Position.prepare(); // To be done manually by Scripty when it needs it. + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + // Safari fix + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || element.tagName == 'BODY') { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + // find page position of source + source = $(source); + var p = source.viewportOffset(); + + // find coordinate system to use + element = $(element); + var delta = [0, 0]; + var parent = null; + // delta [0,0] will do fine with position: fixed elements, + // position:absolute needs offsetParent deltas + if (Element.getStyle(element, 'position') == 'absolute') { + parent = element.getOffsetParent(); + delta = parent.viewportOffset(); + } + + // correct by body offsets (fixes Safari) + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + // set position + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Element.Methods.identify.counter = 1; + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + + +if (!document.createRange || Prototype.Browser.Opera) { + Element.Methods.insert = function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = { bottom: insertions }; + + var t = Element._insertionTranslations, content, position, pos, tagName; + + for (position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + pos = t[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + pos.insert(element, content); + continue; + } + + content = Object.toHTML(content); + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + if (t.tags[tagName]) { + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + if (position == 'top' || position == 'after') fragments.reverse(); + fragments.each(pos.insert.curry(element)); + } + else element.insertAdjacentHTML(pos.adjacency, content.stripScripts()); + + content.evalScripts.bind(content).defer(); + } + + return element; + }; +} + +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); + } + }; + Element.Methods._readAttribute = Element.Methods.readAttribute; + Element.Methods.readAttribute = function(element, attribute) { + if (attribute == 'title') return element.title; + return Element._readAttribute(element, attribute); + }; +} + +else if (Prototype.Browser.IE) { + $w('positionedOffset getOffsetParent viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + var position = element.getStyle('position'); + if (position != 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + 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) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = { + read: { + names: { + 'class': 'className', + 'for': 'htmlFor' + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: function(element, attribute) { + var attribute = element.getAttribute(attribute); + return attribute ? attribute.toString().slice(23, -2) : null; + }, + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + }; + + Element._attributeTranslations.write = { + names: Object.clone(Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr, + src: v._getAttr, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); +} + +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; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + // Safari returns margins on body which is incorrect if the child is absolutely + // positioned. For performance reasons, redefine Position.cumulativeOffset for + // KHTML/WebKit only. + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if (Prototype.Browser.IE || Prototype.Browser.Opera) { + // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements + Element.Methods.update = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) return element.update().insert(content); + + content = Object.toHTML(content); + var tagName = element.tagName.toUpperCase(); + + if (tagName in Element._insertionTranslations.tags) { + $A(element.childNodes).each(function(node) { element.removeChild(node) }); + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { element.appendChild(node) }); + } + else element.innerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +if (document.createElement('div').outerHTML) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: { + adjacency: 'beforeBegin', + insert: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + initializeRange: function(element, range) { + range.setStartBefore(element); + } + }, + top: { + adjacency: 'afterBegin', + insert: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + initializeRange: function(element, range) { + range.selectNodeContents(element); + range.collapse(true); + } + }, + bottom: { + adjacency: 'beforeEnd', + insert: function(element, node) { + element.appendChild(node); + } + }, + after: { + adjacency: 'afterEnd', + insert: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + initializeRange: function(element, range) { + range.setStartAfter(element); + } + }, + tags: { + TABLE: ['', '
', 1], + TBODY: ['', '
', 2], + TR: ['', '
', 3], + TD: ['
', '
', 4], + SELECT: ['', 1] + } +}; + +(function() { + this.bottom.initializeRange = this.top.initializeRange; + Object.extend(this.tags, { + THEAD: this.tags.TBODY, + TFOOT: this.tags.TBODY, + TH: this.tags.TD + }); +}).call(Element._insertionTranslations); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var 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.extend = (function() { + if (Prototype.BrowserFeatures.SpecificElementExtensions) + return Prototype.K; + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || element._extendedByPrototype || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName, property, value; + + // extend methods for specific tags + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + for (property in methods) { + value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + // extend methods for all tags (Safari doesn't need this) + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +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, { + "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 (Object.isArray(tagName)) 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; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + 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 (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + +document.viewport = { + getDimensions: function() { + var dimensions = { }; + $w('width height').each(function(d) { + var D = d.capitalize(); + dimensions[d] = self['inner' + D] || + (document.documentElement['client' + D] || document.body['client' + D]); + }); + return dimensions; + }, + + getWidth: function() { + return this.getDimensions().width; + }, + + getHeight: function() { + return this.getDimensions().height; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; +/* Portions of the Selector class are derived from Jack Slocum’s DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create(); + +Selector.prototype = { + initialize: function(expression) { + this.expression = expression.strip(); + this.compileMatcher(); + }, + + compileMatcher: function() { + // Selectors with namespaced attributes can't use the XPath version + if (Prototype.BrowserFeatures.XPath && !(/\[[\w-]*?:/).test(this.expression)) + return this.compileXPathMatcher(); + + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + this.matcher.push(Object.isFunction(c[i]) ? c[i](m) : + new Template(c[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.matcher.push("return h.unique(n);\n}"); + eval(this.matcher.join('\n')); + Selector._cache[this.expression] = this.matcher; + }, + + compileXPathMatcher: function() { + var e = this.expression, ps = Selector.patterns, + x = Selector.xpath, le, m; + + if (Selector._cache[e]) { + this.xpath = Selector._cache[e]; return; + } + + this.matcher = ['.//*']; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + if (m = e.match(ps[i])) { + this.matcher.push(Object.isFunction(x[i]) ? x[i](m) : + new Template(x[i]).evaluate(m)); + e = e.replace(m[0], ''); + break; + } + } + } + + this.xpath = this.matcher.join(''); + Selector._cache[this.expression] = this.xpath; + }, + + findElements: function(root) { + root = root || document; + if (this.xpath) return document._getElementsByXPath(this.xpath, root); + return this.matcher(root); + }, + + match: function(element) { + this.tokens = []; + + var e = this.expression, ps = Selector.patterns, as = Selector.assertions; + var le, p, m; + + while (e && le !== e && (/\S/).test(e)) { + le = e; + for (var i in ps) { + p = ps[i]; + if (m = e.match(p)) { + // use the Selector.assertions methods unless the selector + // is too complex. + if (as[i]) { + this.tokens.push([i, Object.clone(m)]); + e = e.replace(m[0], ''); + } else { + // reluctantly do a document-wide search + // and look for a match in the array + return this.findElements(document).include(element); + } + } + } + } + + var match = true, name, matches; + for (var i = 0, token; token = this.tokens[i]; i++) { + name = token[0], matches = token[1]; + if (!Selector.assertions[name](element, matches)) { + match = false; break; + } + } + + return match; + }, + + toString: function() { + return this.expression; + }, + + inspect: function() { + return "#"; + } +}; + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: "[@#{1}]", + attr: function(m) { + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0 or translate(text(), ' \t\r\n', '') = '')]", + 'checked': "[@checked]", + 'disabled': "[@disabled]", + 'enabled': "[not(@disabled)]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, m, v; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i in p) { + if (m = e.match(p[i])) { + v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m); + exclusion.push("(" + v.substring(1, v.length - 1) + ")"); + e = e.replace(m[0], ''); + break; + } + } + } + return "[not(" + exclusion.join(" and ") + ")]"; + }, + 'nth-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m); + }, + 'nth-last-child': function(m) { + return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m); + }, + 'nth-of-type': function(m) { + return Selector.xpath.pseudos.nth("position() ", m); + }, + 'nth-last-of-type': function(m) { + return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m); + }, + 'first-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m); + }, + 'last-of-type': function(m) { + m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m); + }, + 'only-of-type': function(m) { + var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m); + }, + nth: function(fragment, m) { + var mm, formula = m[6], predicate; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + if (mm = formula.match(/^(\d+)$/)) // digit only + return '[' + fragment + "= " + mm[1] + ']'; + if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (mm[1] == "-") mm[1] = -1; + var a = mm[1] ? Number(mm[1]) : 1; + var b = mm[2] ? Number(mm[2]) : 0; + predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " + + "((#{fragment} - #{b}) div #{a} >= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}"); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}"); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: { + // combinators must be listed first + // (and descendant needs to be last combinator) + laterSibling: /^\s*~\s*/, + child: /^\s*>\s*/, + adjacent: /^\s*\+\s*/, + descendant: /^\s/, + + // selectors follow + tagName: /^\s*(\*|[\w\-]+)(\b|$)?/, + id: /^#([\w\-\*]+)(\b|$)/, + className: /^\.([\w\-\*]+)(\b|$)/, + pseudo: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|\s|(?=:))/, + attrPresence: /^\[([\w]+)\]/, + attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ + }, + + // for Selector.match and Element#match + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return Selector.operators[matches[2]](nodeValue, matches[3]); + } + }, + + handlers: { + // UTILITY FUNCTIONS + // joins two collections + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + // marks an array of nodes for counting + mark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = true; + return nodes; + }, + + unmark: function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._counted = undefined; + return nodes; + }, + + // mark each child node with its position (for nth calls) + // "ofType" flag indicates whether we're indexing for nth-of-type + // rather than nth-child + index: function(parentNode, reverse, ofType) { + parentNode._counted = true; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._counted)) node.nodeIndex = j++; + } + }, + + // filters out duplicates and extends all nodes + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (!(n = nodes[i])._counted) { + n._counted = true; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + // COMBINATOR FUNCTIONS + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, children = [], child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + // TOKEN FUNCTIONS + tagName: function(nodes, root, tagName, combinator) { + tagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + // fastlane for ordinary descendant combinators + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() == tagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + if (!targetNode) return []; + if (!nodes && root == document) return [targetNode]; + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr) { + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + // handles the an+b logic + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._counted) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + // IE treats comments as element nodes + if (node.tagName == '!' || (node.firstChild && !node.innerHTML.match(/^\s*$/))) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._counted) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled) results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv.startsWith(v); }, + '$=': function(nv, v) { return nv.endsWith(v); }, + '*=': function(nv, v) { return nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + nv.toUpperCase() + '-').include('-' + v.toUpperCase() + '-'); } + }, + + matchElements: function(elements, expression) { + var matches = new Selector(expression).findElements(), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._counted) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + var exprs = expressions.join(','), expressions = []; + exprs.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} +var Form = { + reset: function(form) { + $(form).reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (options.hash === undefined) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + // a key is already present; construct an array of values + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Hash.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + return $A($(form).getElementsByTagName('*')).inject([], + function(elements, child) { + if (Form.Element.Serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + } + ); + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Hash.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + 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; + }, + + disable: function(element) { + element = $(element); + element.blur(); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (value === undefined) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (value === undefined) return element.value; + else element.value = value; + }, + + select: function(element, index) { + if (index === undefined) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, value, single = !Object.isArray(index); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + value = this.optionValue(opt); + if (single) { + if (value == index) { + opt.selected = true; + return; + } + } + else opt.selected = index.include(value); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + // extend element because hasAttribute may not be native + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + +Abstract.TimedObserver = function() { }; +Abstract.TimedObserver.prototype = { + initialize: function(element, frequency, callback) { + this.frequency = frequency; + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + this.registerCallback(); + }, + + registerCallback: function() { + setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + onTimerEvent: function() { + var value = this.getValue(); + var changed = (Object.isString(this.lastValue) && Object.isString(value) + ? this.lastValue != value : String(this.lastValue) != String(value)); + if (changed) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}; + +Form.Element.Observer = Class.create(); +Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(); +Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = function() { }; +Abstract.EventObserver.prototype = { + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback.bind(this)); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}; + +Form.Element.EventObserver = Class.create(); +Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(); +Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { + getValue: function() { + return Form.serialize(this.element); + } +}); +if (!window.Event) var Event = { }; + +Object.extend(Event, { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + DOMEvents: ['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', + 'mousemove', 'mouseout', 'keypress', 'keydown', 'keyup', + 'load', 'unload', 'abort', 'error', 'resize', 'scroll', + 'select', 'change', 'submit', 'reset', 'focus', 'blur'], + + cache: { }, + + relatedTarget: function(event) { + var element; + switch(event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } +}); + +Event.Methods = { + element: function(event) { + var node = event.target; + return Element.extend(node.nodeType == Node.TEXT_NODE ? node.parentNode : node); + }, + + findElement: function(event, expression) { + var element = Event.element(event); + return element.match(expression) ? element : element.up(expression); + }, + + isLeftClick: function(event) { + return (((event.which) && (event.which == 1)) || + ((event.button) && (event.button == 1))); + }, + + pointer: function(event) { + return { + x: event.pageX || (event.clientX + + (document.documentElement.scrollLeft || document.body.scrollLeft)), + y: event.pageY || (event.clientY + + (document.documentElement.scrollTop || document.body.scrollTop)) + }; + }, + + pointerX: function(event) { return Event.pointer(event).x }, + pointerY: function(event) { return Event.pointer(event).y }, + + stop: function(event) { + event.preventDefault(); + event.stopPropagation(); + } +}; + +Event.extend = (function() { + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return "[object Event]" } + }); + + return function(event) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + Object.extend(event, { + target: event.srcElement, + relatedTarget: Event.relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + return Object.extend(event, methods); + }; + + } else { + Event.prototype = Event.prototype || document.createEvent("HTMLEvents").__proto__; + Object.extend(Event.prototype, methods); + return Prototype.K; + } +})(); + +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._eventID) return element._eventID; + arguments.callee.id = arguments.callee.id || 1; + return element._eventID = ++arguments.callee.id; + } + + function getDOMEventName(eventName) { + if (!Event.DOMEvents.include(eventName)) return "dataavailable"; + return { keypress: "keydown" }[eventName] || eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (event.eventName && event.eventName != eventName) + return false; + + Event.extend(event); + handler.call(event.target, event); + }; + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + var wrapper = createWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, + + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + if (document.createEvent) { + var event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + var event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return event; + } + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize() +}); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards and John Resig. */ + + var timer, fired = false; + + function fireContentLoadedEvent() { + if (fired) return; + if (timer) window.clearInterval(timer); + document.fire("contentloaded"); + fired = true; + } + + if (document.addEventListener) { + if (Prototype.Browser.WebKit) { + timer = window.setInterval(function() { + if (/loaded|complete/.test(document.readyState)) + fireContentLoadedEvent(); + }, 0); + + Event.observe(window, "load", fireContentLoadedEvent); + + } else { + document.addEventListener("DOMContentLoaded", + fireContentLoadedEvent, false); + } + + } else { + document.write(" + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class property Ajax.activeRequestCount +

+ + + + +
+
+
+
+
+
Ajax.activeRequestCount → Number
+ + +

Represents the number of active XHR requests triggered through +Ajax.Request, Ajax.Updater, or Ajax.PeriodicalUpdater.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/index.html b/doc/1.6.1/ajax/ajax/index.html new file mode 100644 index 000000000..6adccfa12 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.6.1 API documentation | Ajax + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ namespace Ajax +

+ + + + + +
+
+

Namespaces

+
+
+ +
    +
  • +

    Ajax.Responders

    + +

    A repository of global listeners notified about every step of +Prototype-based Ajax requests.

    +
  • +
+
+
+ + +
+
+

Classes

+
+
+ +
    +
  • +

    Ajax.PeriodicalUpdater

    + +

    Periodically performs an Ajax request and updates a container's contents +based on the response text.

    +
  • +
  • +

    Ajax.Request

    + +

    Initiates and processes an Ajax request.

    +
  • +
  • +

    Ajax.Response

    + +

    A wrapper class around XmlHttpRequest for dealing with HTTP responses +of Ajax requests.

    +
  • +
  • +

    Ajax.Updater

    + +

    A class that performs an Ajax request and updates a container's contents +with the contents of the response.

    +
  • +
+
+
+ + + + + + + + +
+
+

Class properties

+
+
+ + +
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/periodicalupdater/index.html b/doc/1.6.1/ajax/ajax/periodicalupdater/index.html new file mode 100644 index 000000000..d235b306e --- /dev/null +++ b/doc/1.6.1/ajax/ajax/periodicalupdater/index.html @@ -0,0 +1,202 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.PeriodicalUpdater + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Ajax.PeriodicalUpdater +

+ + + + +
+
+

Description

+
+
+ +

Periodically performs an Ajax request and updates a container's contents +based on the response text.

+ +

Ajax.PeriodicalUpdater behaves like Ajax.Updater, but performs the +update at a prescribed interval, rather than only once. (Note that it is +not a subclass of Ajax.Updater; it's a wrapper around it.)

+ +

This class addresses the common need of periodical update, as required by +all sorts of "polling" mechanisms (e.g., an online chatroom or an online +mail client).

+ +

The basic idea is to run a regular Ajax.Updater at regular intervals, +keeping track of the response text so it can (optionally) react to +receiving the exact same response consecutively.

+ +

Additional options

+ +

Ajax.PeriodicalUpdater features all the common options and callbacks +described in the Ajaxplus those added by Ajax.Updater.

+ +

It also provides two new options:

+ +
    +
  • frequency (Number; default is 2): How long, in seconds, to wait +between the end of one request and the beginning of the next.
  • +
  • decay (Number; default is 1): The rate at which the frequency +grows when the response received is exactly the same as the previous. +The default of 1 means frequency will never grow; override the +default if a stale response implies it's worthwhile to poll less often. +If decay is set to 2, for instance, frequency will double +(2 seconds, 4 seconds, 8 seconds...) each consecutive time the result +is the same; when the result is different once again, frequency will +revert to its original value.
  • +
+ +

Disabling and re-enabling a PeriodicalUpdater

+ +

You can hit the brakes on a running PeriodicalUpdater by calling +Ajax.PeriodicalUpdater#stop. If you wish to re-enable it later, call +Ajax.PeriodicalUpdater#start.

+
+
+ + + + + + + + +
+
+

Constructor

+
+ +
+ + + +
+
+

Instance methods

+
+
+ + +
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/periodicalupdater/new/index.html b/doc/1.6.1/ajax/ajax/periodicalupdater/new/index.html new file mode 100644 index 000000000..847eec7af --- /dev/null +++ b/doc/1.6.1/ajax/ajax/periodicalupdater/new/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | new Ajax.PeriodicalUpdater + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ constructor new Ajax.PeriodicalUpdater +

+ + + + +
+
+
+
+
+
new(container, url[, options])
+
    +
  • + container + (String | Element) + – The DOM element whose contents to update as a result of the Ajax request. Can be a DOM node or a string that identifies a node's ID. +
  • +
  • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
  • +
  • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
  • +
+ + +

Creates a new Ajax.PeriodicalUpdater.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/periodicalupdater/prototype/start/index.html b/doc/1.6.1/ajax/ajax/periodicalupdater/prototype/start/index.html new file mode 100644 index 000000000..a99ce4f0a --- /dev/null +++ b/doc/1.6.1/ajax/ajax/periodicalupdater/prototype/start/index.html @@ -0,0 +1,138 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.PeriodicalUpdater#start + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Ajax.PeriodicalUpdater#start +

+ + + + +
+
+
+
+
+
Ajax.PeriodicalUpdater#start() → undefined
+ + +

Starts the periodical updater (if it had previously been stopped with +Ajax.PeriodicalUpdater#stop).

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/periodicalupdater/prototype/stop/index.html b/doc/1.6.1/ajax/ajax/periodicalupdater/prototype/stop/index.html new file mode 100644 index 000000000..48a90ee3c --- /dev/null +++ b/doc/1.6.1/ajax/ajax/periodicalupdater/prototype/stop/index.html @@ -0,0 +1,139 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.PeriodicalUpdater#stop + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Ajax.PeriodicalUpdater#stop +

+ + + + +
+
+
+
+
+
Ajax.PeriodicalUpdater#stop() → undefined
+ + +

Stops the periodical updater.

+ +

Also calls the onComplete callback, if one has been defined.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/request/index.html b/doc/1.6.1/ajax/ajax/request/index.html new file mode 100644 index 000000000..3fc498723 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/request/index.html @@ -0,0 +1,239 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Request + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Ajax.Request +

+ + + + +
+
+

Description

+
+
+ +

Initiates and processes an Ajax request.

+ +

Ajax.Request is a general-purpose class for making HTTP requests.

+ +

Automatic JavaScript response evaluation

+ +

If an Ajax request follows the same-origin policy and its response +has a JavaScript-related Content-type, the content of the responseText +property will automatically be passed to eval.

+ +

In other words: you don't even need to provide a callback to leverage +pure-JavaScript Ajax responses. This is the convention that drives Rails's +RJS.

+ +

The list of JavaScript-related MIME-types handled by Prototype is:

+ +
    +
  • application/ecmascript
  • +
  • application/javascript
  • +
  • application/x-ecmascript
  • +
  • application/x-javascript
  • +
  • text/ecmascript
  • +
  • text/javascript
  • +
  • text/x-ecmascript
  • +
  • text/x-javascript
  • +
+ +

The MIME-type string is examined in a case-insensitive manner.

+ +

Methods you may find useful

+ +

Instances of the Request object provide several methods that can come in +handy in your callback functions, especially once the request is complete.

+ +
Is the response a successful one?
+ +

The Ajax.Request#success method examines the XHR object's status +property and follows general HTTP guidelines: unknown status is deemed +successful, as is the whole 2xy status code family. It's a generally +better way of testing your response than the usual +200 == transport.status.

+ +
Getting HTTP response headers
+ +

While you can obtain response headers from the XHR object using its +getResponseHeader method, this makes for verbose code, and several +implementations raise an exception when the header is not found. To make +this easier, you can use the Ajax.Response#getHeader method, which +delegates to the longer version and returns null if an exception occurs:

+ +
new Ajax.Request('/your/url', {
+  onSuccess: function(response) {
+    // Note how we brace against null values
+    if ((response.getHeader('Server') || '').match(/Apache/))
+      ++gApacheCount;
+    // Remainder of the code
+  }
+});
+
+
+ +
Evaluating JSON headers
+ +

Some backends will return JSON not as response text, but in the X-JSON +header. In this case, you don't even need to evaluate the returned JSON +yourself, as Prototype automatically does so. It passes the result as the +headerJSON property of the Ajax.Response object. Note that if there +is no such header — or its contents are invalid — headerJSON will be set +to null.

+ +
new Ajax.Request('/your/url', {
+  onSuccess: function(transport) {
+    transport.headerJSON
+  }
+});
+
+
+
+
+ + + + + + + + +
+
+

Constructor

+
+ +
+ + + +
+
+

Instance methods

+
+
+ + +
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/request/new/index.html b/doc/1.6.1/ajax/ajax/request/new/index.html new file mode 100644 index 000000000..937f00fef --- /dev/null +++ b/doc/1.6.1/ajax/ajax/request/new/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.6.1 API documentation | new Ajax.Request + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ constructor new Ajax.Request +

+ + + + +
+
+
+
+
+
new(url[, options])
+
    +
  • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
  • +
  • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
  • +
+ + +

Creates a new Ajax.Request.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/request/prototype/getheader/index.html b/doc/1.6.1/ajax/ajax/request/prototype/getheader/index.html new file mode 100644 index 000000000..d80459a9e --- /dev/null +++ b/doc/1.6.1/ajax/ajax/request/prototype/getheader/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Request#getHeader + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Ajax.Request#getHeader +

+ + + + +
+
+
+
+
+
Ajax.Request#getHeader(name) → String | null
+
    +
  • + name + (String) + – The name of an HTTP header that may have been part of the response. +
  • +
+ + +

Returns the value of the given response header, or null if that header +was not found.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/request/prototype/success/index.html b/doc/1.6.1/ajax/ajax/request/prototype/success/index.html new file mode 100644 index 000000000..d08ca6000 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/request/prototype/success/index.html @@ -0,0 +1,137 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Request#success + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Ajax.Request#success +

+ + + + +
+
+
+
+
+
Ajax.Request#success() → Boolean
+ + +

Tests whether the request was successful.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/responders/index.html b/doc/1.6.1/ajax/ajax/responders/index.html new file mode 100644 index 000000000..1dc007970 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/responders/index.html @@ -0,0 +1,217 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Responders + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ namespace Ajax.Responders +

+ + + + +
+
+

Description

+
+
+ +

A repository of global listeners notified about every step of +Prototype-based Ajax requests.

+ +

Sometimes, you need to provide generic behaviors over all Ajax operations +happening on the page (through Ajax.Request, Ajax.Updater or +Ajax.PeriodicalUpdater).

+ +

For instance, you might want to automatically show an indicator when an +Ajax request is ongoing, and hide it when none are. You may well want to +factor out exception handling as well, logging those somewhere on the page +in a custom fashion. The possibilities are myriad.

+ +

To achieve this, Prototype provides Ajax.Responders, which lets you +register (and, if you wish, unregister later) responders, which are +objects with specially-named methods. These names come from a set of +general callbacks corresponding to different points in time (or outcomes) +of an Ajax request's life cycle.

+ +

For instance, Prototype automatically registers a responder that maintains +a nifty variable: Ajax.activeRequestCount. This represents, at a given +time, the number of currently active Ajax requests — by monitoring their +onCreate and onComplete events. The code for this is fairly simple:

+ +
Ajax.Responders.register({
+  onCreate: function() {
+    Ajax.activeRequestCount++;
+  },
+  onComplete: function() {
+    Ajax.activeRequestCount--;
+  }
+});
+
+
+ +

Responder callbacks

+ +

The callbacks for responders are similar to the callbacks described in +the Ajax, but take a different signature. They're invoked with +three parameters: the requester object (i.e., the corresponding "instance" +of Ajax.Request), the XMLHttpRequest object, and the result of +evaluating the X-JSON response header, if any (can be null). They also +execute in the context of the responder, bound to the this reference.

+ +
    +
  • onCreate: Triggered whenever a requester object from the Ajax +namespace is created, after its parameters are adjusted and before its +XHR connection is opened. This takes two arguments: the requester +object and the underlying XHR object.
  • +
  • onUninitialized (Not guaranteed): Invoked just after the XHR object +is created.
  • +
  • onLoading (Not guaranteed): Triggered when the underlying XHR object +is being setup, and its connection opened.
  • +
  • onLoaded (Not guaranteed): Triggered once the underlying XHR object +is setup, the connection is open, and it is ready to send its actual +request.
  • +
  • onInteractive (Not guaranteed): Triggered whenever the requester +receives a part of the response (but not the final part), should it +be sent in several packets.
  • +
  • onException: Triggered whenever an XHR error arises. Has a custom +signature: the first argument is the requester (i.e. an Ajax.Request +instance), and the second is the exception object.
  • +
  • onComplete: Triggered at the very end of a request's life-cycle, after +the request completes, status-specific callbacks are called, and possible +automatic behaviors are processed. Guaranteed to run regardless of what +happened during the request.
  • +
+
+
+ + + + + + + + + + +
+
+

Class methods

+
+
+ + +
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/responders/register/index.html b/doc/1.6.1/ajax/ajax/responders/register/index.html new file mode 100644 index 000000000..a4d4a0b7c --- /dev/null +++ b/doc/1.6.1/ajax/ajax/responders/register/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Responders.register + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Ajax.Responders.register +

+ + + + +
+
+
+
+
+
Ajax.Responders.register(responder) → undefined
+
    +
  • + responder + (Object) + – A list of functions with keys corresponding to the names of possible callbacks. +
  • +
+ + +

Add a group of responders to all Ajax requests.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/responders/unregister/index.html b/doc/1.6.1/ajax/ajax/responders/unregister/index.html new file mode 100644 index 000000000..b4a0e985e --- /dev/null +++ b/doc/1.6.1/ajax/ajax/responders/unregister/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Responders.unregister + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Ajax.Responders.unregister +

+ + + + +
+
+
+
+
+
Ajax.Responders.unregister(responder) → undefined
+
    +
  • + responder + (Object) + – A list of functions with keys corresponding to the names of possible callbacks. +
  • +
+ + +

Remove a previously-added group of responders.

+ +

As always, unregistering something requires you to use the very same +object you used at registration. If you plan to use unregister, be sure +to assign your responder to a variable before passing it into +Ajax.Responders#register — don't pass it an object literal.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/getallresponseheaders/index.html b/doc/1.6.1/ajax/ajax/response/getallresponseheaders/index.html new file mode 100644 index 000000000..bbbbd677e --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/getallresponseheaders/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response.getAllResponseHeaders + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Ajax.Response.getAllResponseHeaders +

+ + + + +
+
+
+
+
+
Ajax.Response.getAllResponseHeaders() → String
+ + +

Returns a string containing all headers separated by line breaks; throws +an error if no headers exist. This is just a wrapper around the +XmlHttpRequest method of the same name.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/getresponseheader/index.html b/doc/1.6.1/ajax/ajax/response/getresponseheader/index.html new file mode 100644 index 000000000..56dbafd6d --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/getresponseheader/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response.getResponseHeader + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Ajax.Response.getResponseHeader +

+ + + + +
+
+
+
+
+
Ajax.Response.getResponseHeader(name) → String
+ + +

Returns the value of the requested header if present; throws an error +otherwise. This is just a wrapper around the XmlHttpRequest method of +the same name.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/index.html b/doc/1.6.1/ajax/ajax/response/index.html new file mode 100644 index 000000000..c3d479b91 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/index.html @@ -0,0 +1,212 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Ajax.Response +

+ + + + +
+
+

Description

+
+
+ +

A wrapper class around XmlHttpRequest for dealing with HTTP responses +of Ajax requests.

+ +

An instance of Ajax.Response is passed as the first argument of all Ajax +requests' callbacks. You will not need to create instances of +Ajax.Response yourself.

+
+
+ + + + + + + + + + +
+
+

Class methods

+
+ +
+ +
+
+

Instance properties

+
+ +
+ +
+
+

Instance methods

+
+
+ + +
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/getallheaders/index.html b/doc/1.6.1/ajax/ajax/response/prototype/getallheaders/index.html new file mode 100644 index 000000000..dc70bcd1a --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/getallheaders/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#getAllHeaders + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Ajax.Response#getAllHeaders +

+ + + + +
+
+
+
+
+
Ajax.Response#getAllHeaders() → String | null
+ + +

Returns a string containing all headers separated by line breaks. _Does +not__ throw errors if no headers are present the way its native +counterpart does.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/getheader/index.html b/doc/1.6.1/ajax/ajax/response/prototype/getheader/index.html new file mode 100644 index 000000000..c77aefb73 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/getheader/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#getHeader + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Ajax.Response#getHeader +

+ + + + +
+
+
+
+
+
Ajax.Response#getHeader(name) → String | null
+ + +

See Ajax.Request#getHeader.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/headerjson/index.html b/doc/1.6.1/ajax/ajax/response/prototype/headerjson/index.html new file mode 100644 index 000000000..24c94023b --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/headerjson/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#headerJSON + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#headerJSON +

+ + + + +
+
+
+
+
+
Ajax.Response#headerJSON → Object | Array | null
+ + +

Auto-evaluated content of the X-JSON header if present; null otherwise.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/readystate/index.html b/doc/1.6.1/ajax/ajax/response/prototype/readystate/index.html new file mode 100644 index 000000000..a055df88c --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/readystate/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#readyState + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#readyState +

+ + + + +
+
+
+
+
+
Ajax.Response#readyState → Number
+ + +

The request's current state.

+ +

0 corresponds to "Uninitialized", 1 to "Loading", 2 to +"Loaded", 3 to "Interactive", and 4 to "Complete".

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/request/index.html b/doc/1.6.1/ajax/ajax/response/prototype/request/index.html new file mode 100644 index 000000000..d435fe019 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/request/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#request + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#request +

+ + + + +
+
+
+
+
+
Ajax.Response#request → Ajax.Request | Ajax.Updater
+ + +

The request object itself (an instance of Ajax.Request or +Ajax.Updater).

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/responsejson/index.html b/doc/1.6.1/ajax/ajax/response/prototype/responsejson/index.html new file mode 100644 index 000000000..71240ac68 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/responsejson/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#responseJSON + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#responseJSON +

+ + + + +
+
+
+
+
+
Ajax.Response#responseJSON → Object | Array | null
+ + +

The JSON body of the response if the Content-type of the request is set +to application/json; null otherwise.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/responsetext/index.html b/doc/1.6.1/ajax/ajax/response/prototype/responsetext/index.html new file mode 100644 index 000000000..760ee0647 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/responsetext/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#responseText + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#responseText +

+ + + + +
+
+
+
+
+
Ajax.Response#responseText → String
+ + +

The text body of the response.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/responsexml/index.html b/doc/1.6.1/ajax/ajax/response/prototype/responsexml/index.html new file mode 100644 index 000000000..1da25a90b --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/responsexml/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#responseXML + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#responseXML +

+ + + + +
+
+
+
+
+
Ajax.Response#responseXML → document | null
+ + +

The XML body of the response if the Content-type of the request is set +to application/xml; null otherwise.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/status/index.html b/doc/1.6.1/ajax/ajax/response/prototype/status/index.html new file mode 100644 index 000000000..52145802e --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/status/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#status + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#status +

+ + + + +
+
+
+
+
+
Ajax.Response#status → Number
+ + +

The HTTP status code sent by the server.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/statustext/index.html b/doc/1.6.1/ajax/ajax/response/prototype/statustext/index.html new file mode 100644 index 000000000..b90d3e6f2 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/statustext/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#statusText + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#statusText +

+ + + + +
+
+
+
+
+
Ajax.Response#statusText → String
+ + +

The HTTP status text sent by the server.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/response/prototype/transport/index.html b/doc/1.6.1/ajax/ajax/response/prototype/transport/index.html new file mode 100644 index 000000000..291d3d504 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/response/prototype/transport/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Response#transport + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance property Ajax.Response#transport +

+ + + + +
+
+
+
+
+
Ajax.Response#transport → XmlHttpRequest
+ + +

The native XmlHttpRequest object itself.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/updater/index.html b/doc/1.6.1/ajax/ajax/updater/index.html new file mode 100644 index 000000000..4ce370265 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/updater/index.html @@ -0,0 +1,225 @@ + + + + + Prototype v1.6.1 API documentation | Ajax.Updater + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Ajax.Updater +

+ + + + +
+
+

Description

+
+
+ +

A class that performs an Ajax request and updates a container's contents +with the contents of the response.

+ +

Ajax.Updater is a subclass of Ajax.Request built for a common +use-case.

+ +

Example

+ +
new Ajax.Updater('items', '/items', {
+  parameters: { text: $F('text') }
+});
+
+
+ +

This example will make a request to the URL /items (with the given +parameters); it will then replace the contents of the element with the ID +of items with whatever response it receives.

+ +

Callbacks

+ +

Ajax.Updater supports all the callbacks listed in the Ajax. +Note that the onComplete callback will be invoked after the element +is updated.

+ +

Additional options

+ +

Ajax.Updater has some options of its own apart from the common options +described in the Ajax:

+ +
    +
  • evalScripts (Boolean; defaults to false): Whether <script> +elements in the response text should be evaluated.
  • +
  • insertion (String): By default, Element.update is used, meaning +the contents of the response will replace the entire contents of the +container. You may instead insert the response text without disrupting +existing contents. The insertion option takes one of four strings — +top, bottom, before, or after — and inserts the contents of the +response in the manner described by Element#insert.
  • +
+ +

More About `evalScripts`

+ +

If you use evalScripts: true, any inline <script> block will be evaluated. +This does not mean it will be evaluated in the global scope; it won't, and that +has important ramifications for your var and function statements. Also note +that only inline <script> blocks are supported; external scripts are ignored. +See String#evalScripts for the details.

+ +

Single container, or success/failure split?

+ +

The examples above all assume you're going to update the same container +whether your request succeeds or fails. Instead, you may want to update +only for successful requests, or update a different container on failed +requests.

+ +

To achieve this, you can pass an object instead of a DOM element for the +container parameter. This object must have a success property whose +value identifies the container to be updated on successful requests.

+ +

If you also provide it with a failure property, its value will be used as +the container for failed requests.

+ +

In the following code, only successful requests get an update:

+ +
new Ajax.Updater({ success: 'items' }, '/items', {
+  parameters: { text: $F('text') },
+  insertion: 'bottom'
+});
+
+
+ +

This next example assumes failed requests will deliver an error message as +response text — one that should be shown to the user in another area:

+ +
new Ajax.Updater({ success: 'items', failure: 'notice' }, '/items',
+  parameters: { text: $F('text') },
+  insertion: 'bottom'
+});
+
+
+
+
+ + + + + + + + +
+
+

Constructor

+
+ +
+ + + + +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/ajax/updater/new/index.html b/doc/1.6.1/ajax/ajax/updater/new/index.html new file mode 100644 index 000000000..8f1f851f3 --- /dev/null +++ b/doc/1.6.1/ajax/ajax/updater/new/index.html @@ -0,0 +1,152 @@ + + + + + Prototype v1.6.1 API documentation | new Ajax.Updater + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ constructor new Ajax.Updater +

+ + + + +
+
+
+
+
+
new(container, url[, options])
+
    +
  • + container + (String | Element) + – The DOM element whose contents to update as a result of the Ajax request. Can be a DOM node or a string that identifies a node's ID. +
  • +
  • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
  • +
  • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
  • +
+ + +

Creates a new Ajax.Updater.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/ajax/index.html b/doc/1.6.1/ajax/index.html new file mode 100644 index 000000000..fff4ee170 --- /dev/null +++ b/doc/1.6.1/ajax/index.html @@ -0,0 +1,262 @@ + + + + + Prototype v1.6.1 API documentation | Ajax section + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +

+ section Ajax section +

+ + + + +
+
+

Description

+
+
+ +

Prototype's APIs around the XmlHttpRequest object.

+ +

The Prototype framework enables you to deal with Ajax calls in a manner that is +both easy and compatible with all modern browsers.

+ +

Actual requests are made by creating instances of Ajax.Request.

+ +

Request headers

+ +

The following headers are sent with all Ajax requests (and can be +overridden with the requestHeaders option described below):

+ +
    +
  • X-Requested-With is set to XMLHttpRequest.
  • +
  • X-Prototype-Version is set to Prototype's current version (e.g., +1.6.0.3).
  • +
  • Accept is set to text/javascript, text/html, application/xml, +text/xml, * / *
  • +
  • Content-type is automatically determined based on the contentType +and encoding options.
  • +
+ +

Ajax options

+ +

All Ajax classes share a common set of options and callbacks. +Callbacks are called at various points in the life-cycle of a request, and +always feature the same list of arguments.

+ +
Common options
+ +
    +
  • asynchronous (Boolean; default true): Determines whether +XMLHttpRequest is used asynchronously or not. Synchronous usage is +strongly discouraged — it halts all script execution for the +duration of the request and blocks the browser UI.
  • +
  • contentType (String; default application/x-www-form-urlencoded): +The Content-type header for your request. Change this header if you +want to send data in another format (like XML).
  • +
  • encoding (String; default UTF-8): The encoding for the contents +of your request. It is best left as-is, but should weird encoding issues +arise, you may have to tweak this.
  • +
  • method (String; default post): The HTTP method to use for the +request. The other common possibility is get. Abiding by Rails +conventions, Prototype also reacts to other HTTP verbs (such as put and +delete) by submitting via post and adding a extra _method parameter +with the originally-requested method.
  • +
  • parameters (String): The parameters for the request, which will be +encoded into the URL for a get method, or into the request body for the +other methods. This can be provided either as a URL-encoded string, a +Hash, or a plain Object.
  • +
  • postBody (String): Specific contents for the request body on a +post method. If it is not provided, the contents of the parameters +option will be used instead.
  • +
  • requestHeaders (Object): A set of key-value pairs, with properties +representing header names.
  • +
  • evalJS (Boolean | String; default true): Automatically evals +the content of Ajax.Response#responseText and populates +Ajax.Response#responseJSON with it if the Content-type returned by +the server is set to application/json. If the request doesn't obey +same-origin policy, the content is sanitized before evaluation. If you +need to force evalutation, pass 'force'. To prevent it altogether, pass +false.
  • +
  • sanitizeJSON (Boolean; default is false for same-origin requests, +true otherwise): Sanitizes the contents of +Ajax.Response#responseText before evaluating it.
  • +
+ +

Common callbacks

+ +

When used on individual instances, all callbacks (except onException) are +invoked with two parameters: the XMLHttpRequest object and the result of +evaluating the X-JSON response header, if any (can be null).

+ +

For another way of describing their chronological order and which callbacks +are mutually exclusive, see Ajax.Request.

+ +
    +
  • onCreate: Triggered when the Ajax.Request object is initialized. +This is after the parameters and the URL have been processed, but +before opening the connection via the XHR object.
  • +
  • onUninitialized (Not guaranteed): Invoked just after the XHR object +is created.
  • +
  • onLoading (Not guaranteed): Triggered when the underlying XHR object +is being setup, and its connection opened.
  • +
  • onLoaded (Not guaranteed): Triggered once the underlying XHR object +is setup, the connection is open, and it is ready to send its actual +request.
  • +
  • onInteractive (Not guaranteed): Triggered whenever the requester +receives a part of the response (but not the final part), should it +be sent in several packets.
  • +
  • onSuccess: Invoked when a request completes and its status code is +undefined or belongs in the 2xy family. This is skipped if a +code-specific callback is defined (e.g., on200), and happens before +onComplete.
  • +
  • onFailure: Invoked when a request completes and its status code exists +but is not in the 2xy family. This is skipped if a code-specific +callback is defined (e.g. on403), and happens before onComplete.
  • +
  • onXYZ (with XYZ representing any HTTP status code): Invoked just +after the response is complete _if_ the status code is the exact code +used in the callback name. Prevents execution of onSuccess and +onFailure. Happens before onComplete.
  • +
  • onException: Triggered whenever an XHR error arises. Has a custom +signature: the first argument is the requester (i.e. an Ajax.Request +instance), and the second is the exception object.
  • +
  • onComplete: Triggered at the very end of a request's life-cycle, after +the request completes, status-specific callbacks are called, and possible +automatic behaviors are processed. Guaranteed to run regardless of what +happened during the request.
  • +
+
+
+ + + +
+
+

Utilities

+
+
+ +
    +
+
+
+ + +
+
+

Namespaces

+
+
+ + +
+
+ + + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/abstract/eventobserver/index.html b/doc/1.6.1/dom/abstract/eventobserver/index.html new file mode 100644 index 000000000..5684e9314 --- /dev/null +++ b/doc/1.6.1/dom/abstract/eventobserver/index.html @@ -0,0 +1,126 @@ + + + + + Prototype v1.6.1 API documentation | Abstract.EventObserver + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Abstract.EventObserver +

+ + + + + + + + + + + + + + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/abstract/index.html b/doc/1.6.1/dom/abstract/index.html new file mode 100644 index 000000000..635bee561 --- /dev/null +++ b/doc/1.6.1/dom/abstract/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.6.1 API documentation | Abstract + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ namespace Abstract +

+ + + + + + +
+
+

Classes

+
+
+ +
    +
  • +

    Abstract.EventObserver

    + +
  • +
  • +

    Abstract.TimedObserver

    + +

    An abstract DOM element observer class, subclasses of which can be used to periodically +check a value and trigger a callback when the value has changed.

    +
  • +
+
+
+ + + + + + + + + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/abstract/timedobserver/index.html b/doc/1.6.1/dom/abstract/timedobserver/index.html new file mode 100644 index 000000000..3a82df186 --- /dev/null +++ b/doc/1.6.1/dom/abstract/timedobserver/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Abstract.TimedObserver + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Abstract.TimedObserver +

+ + + + +
+
+

Description

+
+
+ +

An abstract DOM element observer class, subclasses of which can be used to periodically +check a value and trigger a callback when the value has changed.

+ +

A TimedObserver object will try to check a value using the getValue() +instance method which must be defined by the subclass. There are two out-of-the-box subclasses: +Form.Observer, which serializes a form and triggers when the result has changed; and +Form.Element.Observer, which triggers when the value of a given form field changes.

+ +

Creating Your Own TimedObserver Implementations

+ +

It's easy to create your own TimedObserver implementations: Simply subclass TimedObserver +and provide the getValue() method. For example, this is the complete source code for +Form.Element.Observer:

+ +
Form.Element.Observer = Class.create(Abstract.TimedObserver, {
+  getValue: function() {
+    return Form.Element.getValue(this.element);
+  }
+});
+
+
+
+
+ + + + + + + + +
+
+

Constructor

+
+ +
+ + + + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/abstract/timedobserver/new/index.html b/doc/1.6.1/dom/abstract/timedobserver/new/index.html new file mode 100644 index 000000000..f9dca0ad4 --- /dev/null +++ b/doc/1.6.1/dom/abstract/timedobserver/new/index.html @@ -0,0 +1,152 @@ + + + + + Prototype v1.6.1 API documentation | new Abstract.TimedObserver + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ constructor new Abstract.TimedObserver +

+ + + + +
+
+
+
+
+
new(element, frequency, callback)
+
    +
  • + element + (String | Element) + – The DOM element to watch. Can be an element instance or an ID. +
  • +
  • + frequency + (Number) + – The frequency, in seconds — e.g., 0.33 to check for changes every third of a second. +
  • +
  • + callback + (Function) + – The callback to trigger when the value changes. +
  • +
+ + +

Initializes an Abstract.TimedObserver; used by subclasses.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/fire/index.html b/doc/1.6.1/dom/document/fire/index.html new file mode 100644 index 000000000..a03cfa124 --- /dev/null +++ b/doc/1.6.1/dom/document/fire/index.html @@ -0,0 +1,137 @@ + + + + + Prototype v1.6.1 API documentation | document.fire + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method document.fire +

+ + + + +
+
+
+
+
+
document.fire(eventName[, memo[, bubble = true]]) → Event
+ + +

See Event.fire.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/index.html b/doc/1.6.1/dom/document/index.html new file mode 100644 index 000000000..73484550f --- /dev/null +++ b/doc/1.6.1/dom/document/index.html @@ -0,0 +1,187 @@ + + + + + Prototype v1.6.1 API documentation | document + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ namespace document +

+ + + + +
+
+

Description

+
+
+ +

Prototype extends the built-in document object with several convenience +methods related to events.

+
+
+ + +
+
+

Namespaces

+
+
+ +
    +
  • +

    document.viewport

    + +

    The document.viewport namespace contains methods that return information +about the viewport — the rectangle that represents the portion of a web +page within view. In other words, it's the browser window minus all chrome.

    +
  • +
+
+
+ + + + + + + + + +
+
+

Class methods

+
+
+ + +
+
+ +
+
+

Class properties

+
+
+ + +
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/loaded/index.html b/doc/1.6.1/dom/document/loaded/index.html new file mode 100644 index 000000000..59268f6f5 --- /dev/null +++ b/doc/1.6.1/dom/document/loaded/index.html @@ -0,0 +1,137 @@ + + + + + Prototype v1.6.1 API documentation | document.loaded + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class property document.loaded +

+ + + + +
+
+
+
+
+
document.loaded → Boolean
+ + +

Whether the full DOM tree is ready for manipulation.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/observe/index.html b/doc/1.6.1/dom/document/observe/index.html new file mode 100644 index 000000000..fe2eeac34 --- /dev/null +++ b/doc/1.6.1/dom/document/observe/index.html @@ -0,0 +1,137 @@ + + + + + Prototype v1.6.1 API documentation | document.observe + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method document.observe +

+ + + + +
+
+
+
+
+
document.observe(eventName, handler) → Element
+ + +

See Event.observe.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/stopobserving/index.html b/doc/1.6.1/dom/document/stopobserving/index.html new file mode 100644 index 000000000..8f7e117af --- /dev/null +++ b/doc/1.6.1/dom/document/stopobserving/index.html @@ -0,0 +1,137 @@ + + + + + Prototype v1.6.1 API documentation | document.stopObserving + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method document.stopObserving +

+ + + + +
+
+
+
+
+
document.stopObserving([eventName[, handler]]) → Element
+ + +

See Event.stopObserving.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/viewport/getdimensions/index.html b/doc/1.6.1/dom/document/viewport/getdimensions/index.html new file mode 100644 index 000000000..303066a7f --- /dev/null +++ b/doc/1.6.1/dom/document/viewport/getdimensions/index.html @@ -0,0 +1,140 @@ + + + + + Prototype v1.6.1 API documentation | document.viewport.getDimensions + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method document.viewport.getDimensions +

+ + + + +
+
+
+
+
+
document.viewport.getDimensions() → Object
+ + +

Returns the size of the viewport.

+ +

Returns an object of the form { width: Number, height: Number }.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/viewport/getheight/index.html b/doc/1.6.1/dom/document/viewport/getheight/index.html new file mode 100644 index 000000000..314cca3b0 --- /dev/null +++ b/doc/1.6.1/dom/document/viewport/getheight/index.html @@ -0,0 +1,138 @@ + + + + + Prototype v1.6.1 API documentation | document.viewport.getHeight + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method document.viewport.getHeight +

+ + + + +
+
+
+
+
+
document.viewport.getHeight() → Number
+ + +

Returns the height of the viewport.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/viewport/getscrolloffsets/index.html b/doc/1.6.1/dom/document/viewport/getscrolloffsets/index.html new file mode 100644 index 000000000..c35632b45 --- /dev/null +++ b/doc/1.6.1/dom/document/viewport/getscrolloffsets/index.html @@ -0,0 +1,141 @@ + + + + + Prototype v1.6.1 API documentation | document.viewport.getScrollOffsets + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method document.viewport.getScrollOffsets +

+ + + + +
+
+
+
+
+
document.viewport.getScrollOffsets() → Array
+ + +

Returns the viewport's horizontal and vertical scroll offsets.

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/viewport/getwidth/index.html b/doc/1.6.1/dom/document/viewport/getwidth/index.html new file mode 100644 index 000000000..d3a12e28f --- /dev/null +++ b/doc/1.6.1/dom/document/viewport/getwidth/index.html @@ -0,0 +1,138 @@ + + + + + Prototype v1.6.1 API documentation | document.viewport.getWidth + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method document.viewport.getWidth +

+ + + + +
+
+
+
+
+
document.viewport.getWidth() → Number
+ + +

Returns the width of the viewport.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/document/viewport/index.html b/doc/1.6.1/dom/document/viewport/index.html new file mode 100644 index 000000000..253870107 --- /dev/null +++ b/doc/1.6.1/dom/document/viewport/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | document.viewport + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ namespace document.viewport +

+ + + + +
+
+

Description

+
+
+ +

The document.viewport namespace contains methods that return information +about the viewport — the rectangle that represents the portion of a web +page within view. In other words, it's the browser window minus all chrome.

+
+
+ + + + + + + + + + +
+
+

Class methods

+
+ +
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/dollar/index.html b/doc/1.6.1/dom/dollar/index.html new file mode 100644 index 000000000..6b6de9d03 --- /dev/null +++ b/doc/1.6.1/dom/dollar/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | $ + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ utility $ +

+ + + + +
+
+
+
+
+
$(id) → Element
$(id...) → [Element]...
+
    +
  • + id + (String | Element) + – A DOM node or a string that references a node's ID. +
  • +
+ + +

If provided with a string, returns the element in the document with +matching ID; otherwise returns the passed element.

+ +

Takes in an arbitrary number of arguments. Returns one Element if given +one argument; otherwise returns an array of Elements.

+ +

All elements returned by the function are "extended" with Element +instance methods.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/dollarf/index.html b/doc/1.6.1/dom/dollarf/index.html new file mode 100644 index 000000000..ce7231d78 --- /dev/null +++ b/doc/1.6.1/dom/dollarf/index.html @@ -0,0 +1,133 @@ + + + + + Prototype v1.6.1 API documentation | $F + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ utility $F +

+ + + + +
+
+
+
+
+
$F(element) → String | Array
+ + + + + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/absolutize/index.html b/doc/1.6.1/dom/element/absolutize/index.html new file mode 100644 index 000000000..e3fb00dd8 --- /dev/null +++ b/doc/1.6.1/dom/element/absolutize/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.absolutize + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.absolutize +

+ + + + +
+
+
+
+
+
Element.absolutize(element) → Element
+ + +

Turns element into an absolutely-positioned element without changing +its position in the page layout.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/addclassname/index.html b/doc/1.6.1/dom/element/addclassname/index.html new file mode 100644 index 000000000..26e9af564 --- /dev/null +++ b/doc/1.6.1/dom/element/addclassname/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.addClassName + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.addClassName +

+ + + + +
+
+
+
+
+
Element.addClassName(element, className) → Element
+ + +

Adds a CSS class to element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/addmethods/index.html b/doc/1.6.1/dom/element/addmethods/index.html new file mode 100644 index 000000000..6a7321269 --- /dev/null +++ b/doc/1.6.1/dom/element/addmethods/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.addMethods + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.addMethods +

+ + + + +
+
+
+
+
+
Element.addMethods(methods) → undefined
Element.addMethods(tagName, methods) → undefined
+ + +

Takes a hash of methods and makes them available as methods of extended +elements and of the Element object.

+ +

The second usage form is for adding methods only to specific tag names.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/adjacent/index.html b/doc/1.6.1/dom/element/adjacent/index.html new file mode 100644 index 000000000..a973e7dd1 --- /dev/null +++ b/doc/1.6.1/dom/element/adjacent/index.html @@ -0,0 +1,277 @@ + + + + + Prototype v1.6.1 API documentation | Element.adjacent + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.adjacent +

+ + + + +
+
+
+
+
+
Element.adjacent(element, selector...) → [Element…]
+
    +
  • + selector + (String) + – A CSS selector. +
  • +
+ + +

Finds all siblings of the current element that match the given +selector(s).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/ancestors/index.html b/doc/1.6.1/dom/element/ancestors/index.html new file mode 100644 index 000000000..82a4b53b0 --- /dev/null +++ b/doc/1.6.1/dom/element/ancestors/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.ancestors + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.ancestors +

+ + + + +
+
+
+
+
+
Element.ancestors(element) → [Element…]
+ + +

Collects all of element's ancestors and returns them as an array of +elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/childelements/index.html b/doc/1.6.1/dom/element/childelements/index.html new file mode 100644 index 000000000..66d2bf868 --- /dev/null +++ b/doc/1.6.1/dom/element/childelements/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.childElements + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.childElements +

+ + + + +
+
+
+
+
+
Element.childElements(element) → [Element…]
+ + + + + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/classnames/index.html b/doc/1.6.1/dom/element/classnames/index.html new file mode 100644 index 000000000..2c8d09b89 --- /dev/null +++ b/doc/1.6.1/dom/element/classnames/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.classNames + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.classNames +

+ + + + +
+
+
+
+
+
Element.classNames(element) → [String…]
+ + +

Returns a new instance of Element.ClassNames, an Enumerable +object used to read and write CSS class names of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/cleanwhitespace/index.html b/doc/1.6.1/dom/element/cleanwhitespace/index.html new file mode 100644 index 000000000..b32399d1d --- /dev/null +++ b/doc/1.6.1/dom/element/cleanwhitespace/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.cleanWhitespace + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.cleanWhitespace +

+ + + + +
+
+
+
+
+
Element.cleanWhitespace(element) → Element
+ + +

Removes whitespace-only text node children from element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/clone/index.html b/doc/1.6.1/dom/element/clone/index.html new file mode 100644 index 000000000..0816896ec --- /dev/null +++ b/doc/1.6.1/dom/element/clone/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element.clone + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.clone +

+ + + + +
+
+
+
+
+
Element.clone(element, deep) → Element
+
    +
  • + deep + (Boolean) + – Whether to clone element's descendants as well. +
  • +
+ + +

Returns a duplicate of element.

+ +

A wrapper around DOM Level 2 Node#cloneNode, Element#clone cleans up +any expando properties defined by Prototype.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/cloneposition/index.html b/doc/1.6.1/dom/element/cloneposition/index.html new file mode 100644 index 000000000..18513b55e --- /dev/null +++ b/doc/1.6.1/dom/element/cloneposition/index.html @@ -0,0 +1,276 @@ + + + + + Prototype v1.6.1 API documentation | Element.clonePosition + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.clonePosition +

+ + + + +
+
+
+
+
+
Element.clonePosition(element, source[, options]) → Element
+ + +

Clones the position and/or dimensions of source onto element as +defined by options.

+ +

Valid keys for options are: setLeft, setTop, setWidth, and +setHeight (all booleans which default to true); and offsetTop +and offsetLeft (numbers which default to 0). Use these to control +which aspects of source's layout are cloned and how much to offset +the resulting position of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/cumulativeoffset/index.html b/doc/1.6.1/dom/element/cumulativeoffset/index.html new file mode 100644 index 000000000..7676e96cb --- /dev/null +++ b/doc/1.6.1/dom/element/cumulativeoffset/index.html @@ -0,0 +1,273 @@ + + + + + Prototype v1.6.1 API documentation | Element.cumulativeOffset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.cumulativeOffset +

+ + + + +
+
+
+
+
+
Element.cumulativeOffset(element) → Array
+ + +

Returns the offsets of element from the top left corner of the +document.

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/cumulativescrolloffset/index.html b/doc/1.6.1/dom/element/cumulativescrolloffset/index.html new file mode 100644 index 000000000..856f02c71 --- /dev/null +++ b/doc/1.6.1/dom/element/cumulativescrolloffset/index.html @@ -0,0 +1,273 @@ + + + + + Prototype v1.6.1 API documentation | Element.cumulativeScrollOffset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.cumulativeScrollOffset +

+ + + + +
+
+
+
+
+
Element.cumulativeScrollOffset(element) → Array
+ + +

Calculates the cumulative scroll offset of an element in nested +scrolling containers.

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/descendantof/index.html b/doc/1.6.1/dom/element/descendantof/index.html new file mode 100644 index 000000000..0dc18da1e --- /dev/null +++ b/doc/1.6.1/dom/element/descendantof/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.descendantOf + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.descendantOf +

+ + + + +
+
+
+
+
+
Element.descendantOf(element, ancestor) → Boolean
+ + +

Checks if element is a descendant of ancestor.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/descendants/index.html b/doc/1.6.1/dom/element/descendants/index.html new file mode 100644 index 000000000..de834c5fa --- /dev/null +++ b/doc/1.6.1/dom/element/descendants/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.descendants + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.descendants +

+ + + + +
+
+
+
+
+
Element.descendants(element) → [Element…]
+ + +

Collects all of element's descendants and returns them as an array of +elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/down/index.html b/doc/1.6.1/dom/element/down/index.html new file mode 100644 index 000000000..8238febc6 --- /dev/null +++ b/doc/1.6.1/dom/element/down/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element.down + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.down +

+ + + + +
+
+
+
+
+
Element.down(element[, expression[, index = 0]]) → Element
Element.down(element[, index = 0]) → Element
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Returns element's first descendant (or the Nth descendant, if index +is specified) that matches expression. If no expression is +provided, all descendants are considered. If no descendant matches these +criteria, undefined is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/empty/index.html b/doc/1.6.1/dom/element/empty/index.html new file mode 100644 index 000000000..bd3b87f2f --- /dev/null +++ b/doc/1.6.1/dom/element/empty/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.empty + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.empty +

+ + + + +
+
+
+
+
+
Element.empty(element) → Element
+ + +

Tests whether element is empty (i.e., contains only whitespace).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/extend/index.html b/doc/1.6.1/dom/element/extend/index.html new file mode 100644 index 000000000..29b9ab9c9 --- /dev/null +++ b/doc/1.6.1/dom/element/extend/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.extend + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.extend +

+ + + + +
+
+
+
+
+
Element.extend(element) → Element
+ + +

Extends element with all of the methods contained in Element.Methods +and Element.Methods.Simulated. +If element is an input, textarea, or select tag, it will also be +extended with the methods from Form.Element.Methods. If it is a form +tag, it will also be extended with the methods from Form.Methods.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/fire/index.html b/doc/1.6.1/dom/element/fire/index.html new file mode 100644 index 000000000..dc9e33c73 --- /dev/null +++ b/doc/1.6.1/dom/element/fire/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.fire + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.fire +

+ + + + +
+
+
+
+
+
Element.fire(element, eventName[, memo[, bubble = true]]) → Event
+ + +

See Event.fire.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/firstdescendant/index.html b/doc/1.6.1/dom/element/firstdescendant/index.html new file mode 100644 index 000000000..193aaeb5d --- /dev/null +++ b/doc/1.6.1/dom/element/firstdescendant/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element.firstDescendant + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.firstDescendant +

+ + + + +
+
+
+
+
+
Element.firstDescendant(element) → Element
+ + +

Returns the first child that is an element.

+ +

This is opposed to the firstChild DOM property, which will return +any node, including text nodes.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/getdimensions/index.html b/doc/1.6.1/dom/element/getdimensions/index.html new file mode 100644 index 000000000..b6a40adfb --- /dev/null +++ b/doc/1.6.1/dom/element/getdimensions/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.getDimensions + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.getDimensions +

+ + + + +
+
+
+
+
+
Element.getDimensions(element) → Object
+ + +

Finds the computed width and height of element and returns them as +key/value pairs of an object.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/getelementsbyselector/index.html b/doc/1.6.1/dom/element/getelementsbyselector/index.html new file mode 100644 index 000000000..89ff8fd92 --- /dev/null +++ b/doc/1.6.1/dom/element/getelementsbyselector/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.getElementsBySelector + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.getElementsBySelector +

+ + + + +
+
+
+
+
+
Element.getElementsBySelector(element, selector) → [Element…]
+ + + + + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/getheight/index.html b/doc/1.6.1/dom/element/getheight/index.html new file mode 100644 index 000000000..7405ab3b1 --- /dev/null +++ b/doc/1.6.1/dom/element/getheight/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.getHeight + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.getHeight +

+ + + + +
+
+
+
+
+
Element.getHeight(element) → Number
+ + +

Returns the height of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/getoffsetparent/index.html b/doc/1.6.1/dom/element/getoffsetparent/index.html new file mode 100644 index 000000000..28f2981fe --- /dev/null +++ b/doc/1.6.1/dom/element/getoffsetparent/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.getOffsetParent + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.getOffsetParent +

+ + + + +
+
+
+
+
+
Element.getOffsetParent(element) → Element
+ + +

Returns element's closest positioned ancestor. If none is found, the +body element is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/getopacity/index.html b/doc/1.6.1/dom/element/getopacity/index.html new file mode 100644 index 000000000..cb72500fb --- /dev/null +++ b/doc/1.6.1/dom/element/getopacity/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.getOpacity + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.getOpacity +

+ + + + +
+
+
+
+
+
Element.getOpacity(element) → String | null
+ + +

Returns the opacity of the element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/getstorage/index.html b/doc/1.6.1/dom/element/getstorage/index.html new file mode 100644 index 000000000..5ae26116b --- /dev/null +++ b/doc/1.6.1/dom/element/getstorage/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.getStorage + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.getStorage +

+ + + + +
+
+
+
+
+
Element.getStorage(element) → Hash
+ + +

Returns the Hash object that stores custom metadata for this element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/getstyle/index.html b/doc/1.6.1/dom/element/getstyle/index.html new file mode 100644 index 000000000..9146f1258 --- /dev/null +++ b/doc/1.6.1/dom/element/getstyle/index.html @@ -0,0 +1,278 @@ + + + + + Prototype v1.6.1 API documentation | Element.getStyle + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.getStyle +

+ + + + +
+
+
+
+
+
Element.getStyle(element, style) → String | null
+
    +
  • + style + (String) + – The property name to be retrieved. +
  • +
+ + +

Returns the given CSS property value of element. The property can be +specified in either its CSS form (font-size) or its camelized form +(fontSize).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/getwidth/index.html b/doc/1.6.1/dom/element/getwidth/index.html new file mode 100644 index 000000000..a70b302e4 --- /dev/null +++ b/doc/1.6.1/dom/element/getwidth/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.getWidth + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.getWidth +

+ + + + +
+
+
+
+
+
Element.getWidth(element) → Number
+ + +

Returns the width of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/hasclassname/index.html b/doc/1.6.1/dom/element/hasclassname/index.html new file mode 100644 index 000000000..09d379083 --- /dev/null +++ b/doc/1.6.1/dom/element/hasclassname/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.hasClassName + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.hasClassName +

+ + + + +
+
+
+
+
+
Element.hasClassName(element, className) → Boolean
+ + +

Checks whether element has the given CSS class name.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/hide/index.html b/doc/1.6.1/dom/element/hide/index.html new file mode 100644 index 000000000..3be4e82c2 --- /dev/null +++ b/doc/1.6.1/dom/element/hide/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.hide + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.hide +

+ + + + +
+
+
+
+
+
Element.hide(element) → Element
+ + +

Sets display: none on element. Returns element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/identify/index.html b/doc/1.6.1/dom/element/identify/index.html new file mode 100644 index 000000000..dd6c0fbae --- /dev/null +++ b/doc/1.6.1/dom/element/identify/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.identify + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.identify +

+ + + + +
+
+
+
+
+
Element.identify(element) → String
+ + +

Returns element's ID. If element does not have an ID, one is +generated, assigned to element, and returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/immediatedescendants/index.html b/doc/1.6.1/dom/element/immediatedescendants/index.html new file mode 100644 index 000000000..81f696e9f --- /dev/null +++ b/doc/1.6.1/dom/element/immediatedescendants/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.immediateDescendants + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.immediateDescendants +

+ + + + +
+
+
+
+
+
Element.immediateDescendants(element) → [Element…]
+ + +

Collects all of element's immediate descendants (i.e., children) and +returns them as an array of elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/index.html b/doc/1.6.1/dom/element/index.html new file mode 100644 index 000000000..278c0dae7 --- /dev/null +++ b/doc/1.6.1/dom/element/index.html @@ -0,0 +1,553 @@ + + + + + Prototype v1.6.1 API documentation | Element + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Element +

+ + + + + + + + + + + +
+
+

Constructor

+
+
+ +

new Element

+
+
+ + + + + + + + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/insert/index.html b/doc/1.6.1/dom/element/insert/index.html new file mode 100644 index 000000000..89a94c372 --- /dev/null +++ b/doc/1.6.1/dom/element/insert/index.html @@ -0,0 +1,320 @@ + + + + + Prototype v1.6.1 API documentation | Element.insert + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.insert +

+ + + + +
+
+
+
+
+
Element.insert(element, content) → Element
+ + + +

Inserts content above, below, at the top, and/or at the bottom of the +given element, depending on the option(s) given.

+ +

insert accepts content in any of these forms:

+ +
    +
  • String: A string of HTML to be parsed and rendered
  • +
  • Element: An Element instance to insert
  • +
  • ...any object with a toElement method: The method is called and the resulting element used
  • +
  • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
  • +
+ +

The content argument can be the content to insert, in which case the implied +insertion point is bottom, or an object that specifies one or more insertion +points (e.g., { bottom: "foo", top: "bar" }).

+ +

Accepted insertion points are:

+ +
    +
  • before (as element's previous sibling)
  • +
  • after (as element's next sibling)
  • +
  • top (as element's first child)
  • +
  • bottom (as element's last child)
  • +
+ +

Examples

+ +

Insert the given HTML at the bottom of the element (using the default):

+ +
$('myelement').insert("<p>HTML to append</p>");
+ $('myelement').insert({
+  top: new Element('img', {src: 'logo.png'})
+});
+
+
+ +

Put hrs before and after the element:

+ +
$('myelement').insert({
+  before: "<hr>",
+  after: "<hr>"
+});
+
+
+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/inspect/index.html b/doc/1.6.1/dom/element/inspect/index.html new file mode 100644 index 000000000..67c1e4844 --- /dev/null +++ b/doc/1.6.1/dom/element/inspect/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.inspect + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.inspect +

+ + + + +
+
+
+
+
+
Element.inspect(element) → String
+ + +

Returns the debug-oriented string representation of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/makeclipping/index.html b/doc/1.6.1/dom/element/makeclipping/index.html new file mode 100644 index 000000000..b133c926c --- /dev/null +++ b/doc/1.6.1/dom/element/makeclipping/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.makeClipping + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.makeClipping +

+ + + + +
+
+
+
+
+
Element.makeClipping(element) → Element
+ + +

Simulates the poorly-supported CSS clip property by setting element's +overflow value to hidden.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/makepositioned/index.html b/doc/1.6.1/dom/element/makepositioned/index.html new file mode 100644 index 000000000..8f7619724 --- /dev/null +++ b/doc/1.6.1/dom/element/makepositioned/index.html @@ -0,0 +1,271 @@ + + + + + Prototype v1.6.1 API documentation | Element.makePositioned + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.makePositioned +

+ + + + +
+
+
+
+
+
Element.makePositioned(element) → Element
+ + +

Allows for the easy creation of a CSS containing block by setting +element's CSS position to relative if its initial position is +either static or undefined.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/match/index.html b/doc/1.6.1/dom/element/match/index.html new file mode 100644 index 000000000..c6163398a --- /dev/null +++ b/doc/1.6.1/dom/element/match/index.html @@ -0,0 +1,276 @@ + + + + + Prototype v1.6.1 API documentation | Element.match + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.match +

+ + + + +
+
+
+
+
+
Element.match(element, selector) → boolean
+
    +
  • + selector + (String) + – A CSS selector. +
  • +
+ + +

Checks if element matches the given CSS selector.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/new/index.html b/doc/1.6.1/dom/element/new/index.html new file mode 100644 index 000000000..9061e2031 --- /dev/null +++ b/doc/1.6.1/dom/element/new/index.html @@ -0,0 +1,278 @@ + + + + + Prototype v1.6.1 API documentation | new Element + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ constructor new Element +

+ + + + +
+
+
+
+
+
new(tagName[, attributes])
+
    +
  • + tagName + (String) + – The name of the HTML element to create. +
  • +
  • + attributes + (Object) + – A list of attribute/value pairs to set on the element. +
  • +
+ + +

Creates an HTML element with tagName as the tag name.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/next/index.html b/doc/1.6.1/dom/element/next/index.html new file mode 100644 index 000000000..2b3345eb9 --- /dev/null +++ b/doc/1.6.1/dom/element/next/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element.next + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.next +

+ + + + +
+
+
+
+
+
Element.next(element[, expression[, index = 0]]) → Element
Element.next(element[, index = 0]) → Element
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Returns element's first following sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all following siblings are considered. If none matches these +criteria, undefined is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/nextsiblings/index.html b/doc/1.6.1/dom/element/nextsiblings/index.html new file mode 100644 index 000000000..64707ed6b --- /dev/null +++ b/doc/1.6.1/dom/element/nextsiblings/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.nextSiblings + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.nextSiblings +

+ + + + +
+
+
+
+
+
Element.nextSiblings(element) → [Element…]
+ + +

Collects all of element's next siblings and returns them as an array +of elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/observe/index.html b/doc/1.6.1/dom/element/observe/index.html new file mode 100644 index 000000000..bc5be5f00 --- /dev/null +++ b/doc/1.6.1/dom/element/observe/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.observe + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.observe +

+ + + + +
+
+
+
+
+
Element.observe(element, eventName, handler) → Element
+ + +

See Event.observe.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/positionedoffset/index.html b/doc/1.6.1/dom/element/positionedoffset/index.html new file mode 100644 index 000000000..4fe127299 --- /dev/null +++ b/doc/1.6.1/dom/element/positionedoffset/index.html @@ -0,0 +1,273 @@ + + + + + Prototype v1.6.1 API documentation | Element.positionedOffset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.positionedOffset +

+ + + + +
+
+
+
+
+
Element.positionedOffset(element) → Array
+ + +

Returns element's offset relative to its closest positioned ancestor +(the element that would be returned by Element.getOffsetParent).

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/previous/index.html b/doc/1.6.1/dom/element/previous/index.html new file mode 100644 index 000000000..6c8924309 --- /dev/null +++ b/doc/1.6.1/dom/element/previous/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element.previous + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.previous +

+ + + + +
+
+
+
+
+
Element.previous(element[, expression[, index = 0]]) → Element
Element.previous(element[, index = 0]) → Element
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Returns element's first previous sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all previous siblings are considered. If none matches these +criteria, undefined is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/previoussiblings/index.html b/doc/1.6.1/dom/element/previoussiblings/index.html new file mode 100644 index 000000000..547799cfc --- /dev/null +++ b/doc/1.6.1/dom/element/previoussiblings/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.previousSiblings + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.previousSiblings +

+ + + + +
+
+
+
+
+
Element.previousSiblings(element) → [Element…]
+ + +

Collects all of element's previous siblings and returns them as an +array of elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/absolutize/index.html b/doc/1.6.1/dom/element/prototype/absolutize/index.html new file mode 100644 index 000000000..19affa3d4 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/absolutize/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#absolutize + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#absolutize +

+ + + + +
+
+
+
+
+
Element#absolutize() → Element
+ + +

Turns element into an absolutely-positioned element without changing +its position in the page layout.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/addclassname/index.html b/doc/1.6.1/dom/element/prototype/addclassname/index.html new file mode 100644 index 000000000..78d96c125 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/addclassname/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#addClassName + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#addClassName +

+ + + + +
+
+
+
+
+
Element#addClassName(className) → Element
+ + +

Adds a CSS class to element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/adjacent/index.html b/doc/1.6.1/dom/element/prototype/adjacent/index.html new file mode 100644 index 000000000..720669334 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/adjacent/index.html @@ -0,0 +1,277 @@ + + + + + Prototype v1.6.1 API documentation | Element#adjacent + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#adjacent +

+ + + + +
+
+
+
+
+
Element#adjacent(selector...) → [Element…]
+
    +
  • + selector + (String) + – A CSS selector. +
  • +
+ + +

Finds all siblings of the current element that match the given +selector(s).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/ancestors/index.html b/doc/1.6.1/dom/element/prototype/ancestors/index.html new file mode 100644 index 000000000..7cb5de0c2 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/ancestors/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#ancestors + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#ancestors +

+ + + + +
+
+
+
+
+
Element#ancestors() → [Element…]
+ + +

Collects all of element's ancestors and returns them as an array of +elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/childelements/index.html b/doc/1.6.1/dom/element/prototype/childelements/index.html new file mode 100644 index 000000000..5e5117cf7 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/childelements/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#childElements + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#childElements +

+ + + + +
+
+
+
+
+
Element#childElements() → [Element…]
+ + + + + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/classnames/index.html b/doc/1.6.1/dom/element/prototype/classnames/index.html new file mode 100644 index 000000000..716843bf8 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/classnames/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#classNames + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#classNames +

+ + + + +
+
+
+
+
+
Element#classNames() → [String…]
+ + +

Returns a new instance of Element.ClassNames, an Enumerable +object used to read and write CSS class names of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/cleanwhitespace/index.html b/doc/1.6.1/dom/element/prototype/cleanwhitespace/index.html new file mode 100644 index 000000000..0eabfdbbb --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/cleanwhitespace/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#cleanWhitespace + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#cleanWhitespace +

+ + + + +
+
+
+
+
+
Element#cleanWhitespace() → Element
+ + +

Removes whitespace-only text node children from element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/clone/index.html b/doc/1.6.1/dom/element/prototype/clone/index.html new file mode 100644 index 000000000..ffa5b41f0 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/clone/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element#clone + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#clone +

+ + + + +
+
+
+
+
+
Element#clone(deep) → Element
+
    +
  • + deep + (Boolean) + – Whether to clone element's descendants as well. +
  • +
+ + +

Returns a duplicate of element.

+ +

A wrapper around DOM Level 2 Node#cloneNode, Element#clone cleans up +any expando properties defined by Prototype.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/cloneposition/index.html b/doc/1.6.1/dom/element/prototype/cloneposition/index.html new file mode 100644 index 000000000..58f15ed07 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/cloneposition/index.html @@ -0,0 +1,276 @@ + + + + + Prototype v1.6.1 API documentation | Element#clonePosition + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#clonePosition +

+ + + + +
+
+
+
+
+
Element#clonePosition(source[, options]) → Element
+ + +

Clones the position and/or dimensions of source onto element as +defined by options.

+ +

Valid keys for options are: setLeft, setTop, setWidth, and +setHeight (all booleans which default to true); and offsetTop +and offsetLeft (numbers which default to 0). Use these to control +which aspects of source's layout are cloned and how much to offset +the resulting position of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/cumulativeoffset/index.html b/doc/1.6.1/dom/element/prototype/cumulativeoffset/index.html new file mode 100644 index 000000000..e4e118ec6 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/cumulativeoffset/index.html @@ -0,0 +1,273 @@ + + + + + Prototype v1.6.1 API documentation | Element#cumulativeOffset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#cumulativeOffset +

+ + + + +
+
+
+
+
+
Element#cumulativeOffset() → Array
+ + +

Returns the offsets of element from the top left corner of the +document.

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/cumulativescrolloffset/index.html b/doc/1.6.1/dom/element/prototype/cumulativescrolloffset/index.html new file mode 100644 index 000000000..437a2f058 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/cumulativescrolloffset/index.html @@ -0,0 +1,273 @@ + + + + + Prototype v1.6.1 API documentation | Element#cumulativeScrollOffset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#cumulativeScrollOffset +

+ + + + +
+
+
+
+
+
Element#cumulativeScrollOffset() → Array
+ + +

Calculates the cumulative scroll offset of an element in nested +scrolling containers.

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/descendantof/index.html b/doc/1.6.1/dom/element/prototype/descendantof/index.html new file mode 100644 index 000000000..337cbfb2d --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/descendantof/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#descendantOf + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#descendantOf +

+ + + + +
+
+
+
+
+
Element#descendantOf(ancestor) → Boolean
+ + +

Checks if element is a descendant of ancestor.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/descendants/index.html b/doc/1.6.1/dom/element/prototype/descendants/index.html new file mode 100644 index 000000000..b0cfc4d76 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/descendants/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#descendants + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#descendants +

+ + + + +
+
+
+
+
+
Element#descendants() → [Element…]
+ + +

Collects all of element's descendants and returns them as an array of +elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/down/index.html b/doc/1.6.1/dom/element/prototype/down/index.html new file mode 100644 index 000000000..646eee8ed --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/down/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element#down + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#down +

+ + + + +
+
+
+
+
+
Element#down([expression[, index = 0]]) → Element
Element#down([index = 0]) → Element
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Returns element's first descendant (or the Nth descendant, if index +is specified) that matches expression. If no expression is +provided, all descendants are considered. If no descendant matches these +criteria, undefined is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/empty/index.html b/doc/1.6.1/dom/element/prototype/empty/index.html new file mode 100644 index 000000000..10a37a0f2 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/empty/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#empty + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#empty +

+ + + + +
+
+
+
+
+
Element#empty() → Element
+ + +

Tests whether element is empty (i.e., contains only whitespace).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/fire/index.html b/doc/1.6.1/dom/element/prototype/fire/index.html new file mode 100644 index 000000000..cdc4f55a9 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/fire/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#fire + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#fire +

+ + + + +
+
+
+
+
+
Element#fire(eventName[, memo[, bubble = true]]) → Event
+ + +

See Event.fire.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/firstdescendant/index.html b/doc/1.6.1/dom/element/prototype/firstdescendant/index.html new file mode 100644 index 000000000..637d77237 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/firstdescendant/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element#firstDescendant + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#firstDescendant +

+ + + + +
+
+
+
+
+
Element#firstDescendant() → Element
+ + +

Returns the first child that is an element.

+ +

This is opposed to the firstChild DOM property, which will return +any node, including text nodes.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/getdimensions/index.html b/doc/1.6.1/dom/element/prototype/getdimensions/index.html new file mode 100644 index 000000000..273378d40 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/getdimensions/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#getDimensions + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#getDimensions +

+ + + + +
+
+
+
+
+
Element#getDimensions() → Object
+ + +

Finds the computed width and height of element and returns them as +key/value pairs of an object.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/getelementsbyselector/index.html b/doc/1.6.1/dom/element/prototype/getelementsbyselector/index.html new file mode 100644 index 000000000..61495073e --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/getelementsbyselector/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#getElementsBySelector + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#getElementsBySelector +

+ + + + +
+
+
+
+
+
Element#getElementsBySelector(selector) → [Element…]
+ + + + + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/getheight/index.html b/doc/1.6.1/dom/element/prototype/getheight/index.html new file mode 100644 index 000000000..38a2ad343 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/getheight/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#getHeight + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#getHeight +

+ + + + +
+
+
+
+
+
Element#getHeight() → Number
+ + +

Returns the height of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/getoffsetparent/index.html b/doc/1.6.1/dom/element/prototype/getoffsetparent/index.html new file mode 100644 index 000000000..73a30e5d4 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/getoffsetparent/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#getOffsetParent + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#getOffsetParent +

+ + + + +
+
+
+
+
+
Element#getOffsetParent() → Element
+ + +

Returns element's closest positioned ancestor. If none is found, the +body element is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/getopacity/index.html b/doc/1.6.1/dom/element/prototype/getopacity/index.html new file mode 100644 index 000000000..1383ae7cb --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/getopacity/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#getOpacity + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#getOpacity +

+ + + + +
+
+
+
+
+
Element#getOpacity() → String | null
+ + +

Returns the opacity of the element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/getstorage/index.html b/doc/1.6.1/dom/element/prototype/getstorage/index.html new file mode 100644 index 000000000..58991f2e9 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/getstorage/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#getStorage + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#getStorage +

+ + + + +
+
+
+
+
+
Element#getStorage() → Hash
+ + +

Returns the Hash object that stores custom metadata for this element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/getstyle/index.html b/doc/1.6.1/dom/element/prototype/getstyle/index.html new file mode 100644 index 000000000..611aaac5b --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/getstyle/index.html @@ -0,0 +1,278 @@ + + + + + Prototype v1.6.1 API documentation | Element#getStyle + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#getStyle +

+ + + + +
+
+
+
+
+
Element#getStyle(style) → String | null
+
    +
  • + style + (String) + – The property name to be retrieved. +
  • +
+ + +

Returns the given CSS property value of element. The property can be +specified in either its CSS form (font-size) or its camelized form +(fontSize).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/getwidth/index.html b/doc/1.6.1/dom/element/prototype/getwidth/index.html new file mode 100644 index 000000000..58802a733 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/getwidth/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#getWidth + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#getWidth +

+ + + + +
+
+
+
+
+
Element#getWidth() → Number
+ + +

Returns the width of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/hasclassname/index.html b/doc/1.6.1/dom/element/prototype/hasclassname/index.html new file mode 100644 index 000000000..432cc7a01 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/hasclassname/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#hasClassName + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#hasClassName +

+ + + + +
+
+
+
+
+
Element#hasClassName(className) → Boolean
+ + +

Checks whether element has the given CSS class name.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/hide/index.html b/doc/1.6.1/dom/element/prototype/hide/index.html new file mode 100644 index 000000000..9db4ce8f0 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/hide/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#hide + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#hide +

+ + + + +
+
+
+
+
+
Element#hide() → Element
+ + +

Sets display: none on element. Returns element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/identify/index.html b/doc/1.6.1/dom/element/prototype/identify/index.html new file mode 100644 index 000000000..18891a719 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/identify/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#identify + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#identify +

+ + + + +
+
+
+
+
+
Element#identify() → String
+ + +

Returns element's ID. If element does not have an ID, one is +generated, assigned to element, and returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/immediatedescendants/index.html b/doc/1.6.1/dom/element/prototype/immediatedescendants/index.html new file mode 100644 index 000000000..148eb9d84 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/immediatedescendants/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#immediateDescendants + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#immediateDescendants +

+ + + + +
+
+
+
+
+
Element#immediateDescendants() → [Element…]
+ + +

Collects all of element's immediate descendants (i.e., children) and +returns them as an array of elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/insert/index.html b/doc/1.6.1/dom/element/prototype/insert/index.html new file mode 100644 index 000000000..2ace443dc --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/insert/index.html @@ -0,0 +1,320 @@ + + + + + Prototype v1.6.1 API documentation | Element#insert + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#insert +

+ + + + +
+
+
+
+
+
Element#insert(content) → Element
+ + + +

Inserts content above, below, at the top, and/or at the bottom of the +given element, depending on the option(s) given.

+ +

insert accepts content in any of these forms:

+ +
    +
  • String: A string of HTML to be parsed and rendered
  • +
  • Element: An Element instance to insert
  • +
  • ...any object with a toElement method: The method is called and the resulting element used
  • +
  • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
  • +
+ +

The content argument can be the content to insert, in which case the implied +insertion point is bottom, or an object that specifies one or more insertion +points (e.g., { bottom: "foo", top: "bar" }).

+ +

Accepted insertion points are:

+ +
    +
  • before (as element's previous sibling)
  • +
  • after (as element's next sibling)
  • +
  • top (as element's first child)
  • +
  • bottom (as element's last child)
  • +
+ +

Examples

+ +

Insert the given HTML at the bottom of the element (using the default):

+ +
$('myelement').insert("<p>HTML to append</p>");
+ $('myelement').insert({
+  top: new Element('img', {src: 'logo.png'})
+});
+
+
+ +

Put hrs before and after the element:

+ +
$('myelement').insert({
+  before: "<hr>",
+  after: "<hr>"
+});
+
+
+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/inspect/index.html b/doc/1.6.1/dom/element/prototype/inspect/index.html new file mode 100644 index 000000000..1a31a69ea --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/inspect/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#inspect + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#inspect +

+ + + + +
+
+
+
+
+
Element#inspect() → String
+ + +

Returns the debug-oriented string representation of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/makeclipping/index.html b/doc/1.6.1/dom/element/prototype/makeclipping/index.html new file mode 100644 index 000000000..03ac505c8 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/makeclipping/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#makeClipping + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#makeClipping +

+ + + + +
+
+
+
+
+
Element#makeClipping() → Element
+ + +

Simulates the poorly-supported CSS clip property by setting element's +overflow value to hidden.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/makepositioned/index.html b/doc/1.6.1/dom/element/prototype/makepositioned/index.html new file mode 100644 index 000000000..ca10b9320 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/makepositioned/index.html @@ -0,0 +1,271 @@ + + + + + Prototype v1.6.1 API documentation | Element#makePositioned + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#makePositioned +

+ + + + +
+
+
+
+
+
Element#makePositioned() → Element
+ + +

Allows for the easy creation of a CSS containing block by setting +element's CSS position to relative if its initial position is +either static or undefined.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/match/index.html b/doc/1.6.1/dom/element/prototype/match/index.html new file mode 100644 index 000000000..ed73e8a67 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/match/index.html @@ -0,0 +1,276 @@ + + + + + Prototype v1.6.1 API documentation | Element#match + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#match +

+ + + + +
+
+
+
+
+
Element#match(selector) → boolean
+
    +
  • + selector + (String) + – A CSS selector. +
  • +
+ + +

Checks if element matches the given CSS selector.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/next/index.html b/doc/1.6.1/dom/element/prototype/next/index.html new file mode 100644 index 000000000..46833ee97 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/next/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element#next + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#next +

+ + + + +
+
+
+
+
+
Element#next([expression[, index = 0]]) → Element
Element#next([index = 0]) → Element
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Returns element's first following sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all following siblings are considered. If none matches these +criteria, undefined is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/nextsiblings/index.html b/doc/1.6.1/dom/element/prototype/nextsiblings/index.html new file mode 100644 index 000000000..68f95369a --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/nextsiblings/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#nextSiblings + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#nextSiblings +

+ + + + +
+
+
+
+
+
Element#nextSiblings() → [Element…]
+ + +

Collects all of element's next siblings and returns them as an array +of elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/observe/index.html b/doc/1.6.1/dom/element/prototype/observe/index.html new file mode 100644 index 000000000..9be944523 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/observe/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#observe + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#observe +

+ + + + +
+
+
+
+
+
Element#observe(eventName, handler) → Element
+ + +

See Event.observe.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/positionedoffset/index.html b/doc/1.6.1/dom/element/prototype/positionedoffset/index.html new file mode 100644 index 000000000..02d49ee6f --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/positionedoffset/index.html @@ -0,0 +1,273 @@ + + + + + Prototype v1.6.1 API documentation | Element#positionedOffset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#positionedOffset +

+ + + + +
+
+
+
+
+
Element#positionedOffset() → Array
+ + +

Returns element's offset relative to its closest positioned ancestor +(the element that would be returned by Element.getOffsetParent).

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/previous/index.html b/doc/1.6.1/dom/element/prototype/previous/index.html new file mode 100644 index 000000000..232d9795d --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/previous/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element#previous + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#previous +

+ + + + +
+
+
+
+
+
Element#previous([expression[, index = 0]]) → Element
Element#previous([index = 0]) → Element
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Returns element's first previous sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all previous siblings are considered. If none matches these +criteria, undefined is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/previoussiblings/index.html b/doc/1.6.1/dom/element/prototype/previoussiblings/index.html new file mode 100644 index 000000000..208f78628 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/previoussiblings/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#previousSiblings + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#previousSiblings +

+ + + + +
+
+
+
+
+
Element#previousSiblings() → [Element…]
+ + +

Collects all of element's previous siblings and returns them as an +array of elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/readattribute/index.html b/doc/1.6.1/dom/element/prototype/readattribute/index.html new file mode 100644 index 000000000..20dc896fc --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/readattribute/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#readAttribute + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#readAttribute +

+ + + + +
+
+
+
+
+
Element#readAttribute(attributeName) → String | null
+ + +

Returns the value of element's attribute with the given name.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/recursivelycollect/index.html b/doc/1.6.1/dom/element/prototype/recursivelycollect/index.html new file mode 100644 index 000000000..167348db6 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/recursivelycollect/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element#recursivelyCollect + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#recursivelyCollect +

+ + + + +
+
+
+
+
+
Element#recursivelyCollect(property) → [Element…]
+ + +

Recursively collects elements whose relationship to element is +specified by property. property has to be a property (a method +won't do!) of element that points to a single DOM node (e.g., +nextSibling or parentNode).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/relativize/index.html b/doc/1.6.1/dom/element/prototype/relativize/index.html new file mode 100644 index 000000000..feb148be3 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/relativize/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element#relativize + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#relativize +

+ + + + +
+
+
+
+
+
Element#relativize() → Element
+ + +

Turns element into a relatively-positioned element without changing +its position in the page layout.

+ +

Used to undo a call to Element.absolutize.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/remove/index.html b/doc/1.6.1/dom/element/prototype/remove/index.html new file mode 100644 index 000000000..808dc87da --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/remove/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#remove + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#remove +

+ + + + +
+
+
+
+
+
Element#remove() → Element
+ + +

Completely removes element from the document and returns it.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/removeclassname/index.html b/doc/1.6.1/dom/element/prototype/removeclassname/index.html new file mode 100644 index 000000000..b8149d5ce --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/removeclassname/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#removeClassName + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#removeClassName +

+ + + + +
+
+
+
+
+
Element#removeClassName(className) → Element
+ + +

Removes a CSS class from element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/replace/index.html b/doc/1.6.1/dom/element/prototype/replace/index.html new file mode 100644 index 000000000..77c517173 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/replace/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element#replace + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#replace +

+ + + + +
+
+
+
+
+
Element#replace([newContent]) → Element
+ + +

Replaces element itself with newContent and returns element.

+ +

Keep in mind that this method returns the element that has just been +removed — not the element that took its place.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/retrieve/index.html b/doc/1.6.1/dom/element/prototype/retrieve/index.html new file mode 100644 index 000000000..193cc4085 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/retrieve/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element#retrieve + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#retrieve +

+ + + + +
+
+
+
+
+
Element#retrieve(key[, defaultValue]) → ?
+ + +

Retrieves custom metadata set on element with Element.store.

+ +

If the value is undefined and defaultValue is given, it will be +stored on the element as its new value for that key, then returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/scrollto/index.html b/doc/1.6.1/dom/element/prototype/scrollto/index.html new file mode 100644 index 000000000..b0ce12a21 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/scrollto/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#scrollTo + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#scrollTo +

+ + + + +
+
+
+
+
+
Element#scrollTo() → Element
+ + +

Scrolls the window so that element appears at the top of the viewport.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/select/index.html b/doc/1.6.1/dom/element/prototype/select/index.html new file mode 100644 index 000000000..8153136bc --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/select/index.html @@ -0,0 +1,277 @@ + + + + + Prototype v1.6.1 API documentation | Element#select + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#select +

+ + + + +
+
+
+
+
+
Element#select(selector...) → [Element…]
+
    +
  • + selector + (String) + – A CSS selector. +
  • +
+ + +

Takes an arbitrary number of CSS selectors and returns an array of +descendants of element that match any of them.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/setopacity/index.html b/doc/1.6.1/dom/element/prototype/setopacity/index.html new file mode 100644 index 000000000..7ae29b0bd --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/setopacity/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#setOpacity + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#setOpacity +

+ + + + +
+
+
+
+
+
Element#setOpacity(value) → Element
+ + +

Sets the opacity of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/setstyle/index.html b/doc/1.6.1/dom/element/prototype/setstyle/index.html new file mode 100644 index 000000000..e6e57f5d3 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/setstyle/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element#setStyle + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#setStyle +

+ + + + +
+
+
+
+
+
Element#setStyle(styles) → Element
+ + +

Modifies element's CSS style properties.

+ +

Styles are passed as an object of property-value pairs in which the +properties are specified in their camelized form (e.g., fontSize).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/show/index.html b/doc/1.6.1/dom/element/prototype/show/index.html new file mode 100644 index 000000000..9d74f8689 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/show/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#show + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#show +

+ + + + +
+
+
+
+
+
Element#show() → Element
+ + +

Removes display: none on element. Returns element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/siblings/index.html b/doc/1.6.1/dom/element/prototype/siblings/index.html new file mode 100644 index 000000000..8ff474a72 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/siblings/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#siblings + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#siblings +

+ + + + +
+
+
+
+
+
Element#siblings() → [Element…]
+ + +

Collects all of element's siblings and returns them as an array of +elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/stopobserving/index.html b/doc/1.6.1/dom/element/prototype/stopobserving/index.html new file mode 100644 index 000000000..35181e593 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/stopobserving/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#stopObserving + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#stopObserving +

+ + + + +
+
+
+
+
+
Element#stopObserving([eventName[, handler]]) → Element
+ + +

See Event.stopObserving.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/store/index.html b/doc/1.6.1/dom/element/prototype/store/index.html new file mode 100644 index 000000000..c93a9a09b --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/store/index.html @@ -0,0 +1,271 @@ + + + + + Prototype v1.6.1 API documentation | Element#store + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#store +

+ + + + +
+
+
+
+
+
Element#store(key, value) → Element
+ + +

Stores a key/value pair of custom metadata on the element.

+ +

The metadata can later be retrieved with Element.retrieve.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/toggle/index.html b/doc/1.6.1/dom/element/prototype/toggle/index.html new file mode 100644 index 000000000..5234fc35a --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/toggle/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#toggle + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#toggle +

+ + + + +
+
+
+
+
+
Element#toggle() → Element
+ + +

Toggles the visibility of element. Returns element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/toggleclassname/index.html b/doc/1.6.1/dom/element/prototype/toggleclassname/index.html new file mode 100644 index 000000000..f25e4f4ea --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/toggleclassname/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element#toggleClassName + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#toggleClassName +

+ + + + +
+
+
+
+
+
Element#toggleClassName(className) → Element
+ + +

Toggles the presence of a CSS class on element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/undoclipping/index.html b/doc/1.6.1/dom/element/prototype/undoclipping/index.html new file mode 100644 index 000000000..ab4ed5dc0 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/undoclipping/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#undoClipping + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#undoClipping +

+ + + + +
+
+
+
+
+
Element#undoClipping() → Element
+ + +

Sets element's CSS overflow property back to the value it had +before Element.makeClipping was applied.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/undopositioned/index.html b/doc/1.6.1/dom/element/prototype/undopositioned/index.html new file mode 100644 index 000000000..3901f9887 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/undopositioned/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#undoPositioned + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#undoPositioned +

+ + + + +
+
+
+
+
+
Element#undoPositioned() → Element
+ + +

Sets element back to the state it was in before +Element.makePositioned was applied to it.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/up/index.html b/doc/1.6.1/dom/element/prototype/up/index.html new file mode 100644 index 000000000..797b71604 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/up/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element#up + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#up +

+ + + + +
+
+
+
+
+
Element#up([expression[, index = 0]]) → Element
Element#up([index = 0]) → Element
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Returns element's first ancestor (or the Nth ancestor, if index +is specified) that matches expression. If no expression is +provided, all ancestors are considered. If no ancestor matches these +criteria, undefined is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/update/index.html b/doc/1.6.1/dom/element/prototype/update/index.html new file mode 100644 index 000000000..d87e96878 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/update/index.html @@ -0,0 +1,289 @@ + + + + + Prototype v1.6.1 API documentation | Element#update + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#update +

+ + + + +
+
+
+
+
+
Element#update([newContent]) → Element
+ + +

Replaces the content of element with the newContent argument and +returns element.

+ +

newContent may be in any of these forms:

+ +
    +
  • String: A string of HTML to be parsed and rendered
  • +
  • Element: An Element instance to insert
  • +
  • ...any object with a toElement method: The method is called and the resulting element used
  • +
  • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
  • +
+ +

If newContent is omitted, the element's content is blanked out (i.e., +replaced with an empty string).

+ +

If newContent is a string and contains one or more inline <script> tags, the scripts +are scheduled to be evaluated after a very brief pause (using Function#defer) to allow +the browser to finish updating the DOM. Note that the scripts are evaluated +in the scope of String#evalScripts, not in the global scope, which has important +ramifications for your vars and functions. See String#evalScripts for details.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/viewportoffset/index.html b/doc/1.6.1/dom/element/prototype/viewportoffset/index.html new file mode 100644 index 000000000..615072f34 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/viewportoffset/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element#viewportOffset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#viewportOffset +

+ + + + +
+
+
+
+
+
Element#viewportOffset() → Array
+ + +

Returns the X/Y coordinates of element relative to the viewport.

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/visible/index.html b/doc/1.6.1/dom/element/prototype/visible/index.html new file mode 100644 index 000000000..3e1a0c8f0 --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/visible/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#visible + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#visible +

+ + + + +
+
+
+
+
+
Element#visible() → boolean
+ + +

Tells whether element is visible (i.e., whether its inline display +CSS property is set to none.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/wrap/index.html b/doc/1.6.1/dom/element/prototype/wrap/index.html new file mode 100644 index 000000000..217c5a01e --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/wrap/index.html @@ -0,0 +1,281 @@ + + + + + Prototype v1.6.1 API documentation | Element#wrap + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#wrap +

+ + + + +
+
+
+
+
+
Element#wrap(wrapper[, attributes]) → Element
+
    +
  • + wrapper + (Element | String) + – An element to wrap element inside, or else a string representing the tag name of an element to be created. +
  • +
  • + attributes + (Object) + – A set of attributes to apply to the wrapper element. Refer to the Element constructor for usage. +
  • +
+ + +

Wraps an element inside another, then returns the wrapper.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/prototype/writeattribute/index.html b/doc/1.6.1/dom/element/prototype/writeattribute/index.html new file mode 100644 index 000000000..3ed4728da --- /dev/null +++ b/doc/1.6.1/dom/element/prototype/writeattribute/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element#writeAttribute + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Element#writeAttribute +

+ + + + +
+
+
+
+
+
Element#writeAttribute(attribute[, value = true]) → Element
Element#writeAttribute(attributes) → Element
+ + +

Adds, changes, or removes attributes passed as either a hash or a +name/value pair.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/readattribute/index.html b/doc/1.6.1/dom/element/readattribute/index.html new file mode 100644 index 000000000..60e8c87e0 --- /dev/null +++ b/doc/1.6.1/dom/element/readattribute/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.readAttribute + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.readAttribute +

+ + + + +
+
+
+
+
+
Element.readAttribute(element, attributeName) → String | null
+ + +

Returns the value of element's attribute with the given name.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/recursivelycollect/index.html b/doc/1.6.1/dom/element/recursivelycollect/index.html new file mode 100644 index 000000000..793ff1074 --- /dev/null +++ b/doc/1.6.1/dom/element/recursivelycollect/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element.recursivelyCollect + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.recursivelyCollect +

+ + + + +
+
+
+
+
+
Element.recursivelyCollect(element, property) → [Element…]
+ + +

Recursively collects elements whose relationship to element is +specified by property. property has to be a property (a method +won't do!) of element that points to a single DOM node (e.g., +nextSibling or parentNode).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/relativize/index.html b/doc/1.6.1/dom/element/relativize/index.html new file mode 100644 index 000000000..5f3fecb83 --- /dev/null +++ b/doc/1.6.1/dom/element/relativize/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element.relativize + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.relativize +

+ + + + +
+
+
+
+
+
Element.relativize(element) → Element
+ + +

Turns element into a relatively-positioned element without changing +its position in the page layout.

+ +

Used to undo a call to Element.absolutize.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/remove/index.html b/doc/1.6.1/dom/element/remove/index.html new file mode 100644 index 000000000..a1dd4ccaf --- /dev/null +++ b/doc/1.6.1/dom/element/remove/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.remove + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.remove +

+ + + + +
+
+
+
+
+
Element.remove(element) → Element
+ + +

Completely removes element from the document and returns it.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/removeclassname/index.html b/doc/1.6.1/dom/element/removeclassname/index.html new file mode 100644 index 000000000..4fc448b19 --- /dev/null +++ b/doc/1.6.1/dom/element/removeclassname/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.removeClassName + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.removeClassName +

+ + + + +
+
+
+
+
+
Element.removeClassName(element, className) → Element
+ + +

Removes a CSS class from element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/replace/index.html b/doc/1.6.1/dom/element/replace/index.html new file mode 100644 index 000000000..84a3aa0f8 --- /dev/null +++ b/doc/1.6.1/dom/element/replace/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element.replace + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.replace +

+ + + + +
+
+
+
+
+
Element.replace(element[, newContent]) → Element
+ + +

Replaces element itself with newContent and returns element.

+ +

Keep in mind that this method returns the element that has just been +removed — not the element that took its place.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/retrieve/index.html b/doc/1.6.1/dom/element/retrieve/index.html new file mode 100644 index 000000000..15be6f43e --- /dev/null +++ b/doc/1.6.1/dom/element/retrieve/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element.retrieve + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.retrieve +

+ + + + +
+
+
+
+
+
Element.retrieve(element, key[, defaultValue]) → ?
+ + +

Retrieves custom metadata set on element with Element.store.

+ +

If the value is undefined and defaultValue is given, it will be +stored on the element as its new value for that key, then returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/scrollto/index.html b/doc/1.6.1/dom/element/scrollto/index.html new file mode 100644 index 000000000..159b690d3 --- /dev/null +++ b/doc/1.6.1/dom/element/scrollto/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.scrollTo + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.scrollTo +

+ + + + +
+
+
+
+
+
Element.scrollTo(element) → Element
+ + +

Scrolls the window so that element appears at the top of the viewport.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/select/index.html b/doc/1.6.1/dom/element/select/index.html new file mode 100644 index 000000000..88aa1e3e9 --- /dev/null +++ b/doc/1.6.1/dom/element/select/index.html @@ -0,0 +1,277 @@ + + + + + Prototype v1.6.1 API documentation | Element.select + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.select +

+ + + + +
+
+
+
+
+
Element.select(element, selector...) → [Element…]
+
    +
  • + selector + (String) + – A CSS selector. +
  • +
+ + +

Takes an arbitrary number of CSS selectors and returns an array of +descendants of element that match any of them.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/setopacity/index.html b/doc/1.6.1/dom/element/setopacity/index.html new file mode 100644 index 000000000..7987e31d5 --- /dev/null +++ b/doc/1.6.1/dom/element/setopacity/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.setOpacity + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.setOpacity +

+ + + + +
+
+
+
+
+
Element.setOpacity(element, value) → Element
+ + +

Sets the opacity of element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/setstyle/index.html b/doc/1.6.1/dom/element/setstyle/index.html new file mode 100644 index 000000000..09020115f --- /dev/null +++ b/doc/1.6.1/dom/element/setstyle/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element.setStyle + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.setStyle +

+ + + + +
+
+
+
+
+
Element.setStyle(element, styles) → Element
+ + +

Modifies element's CSS style properties.

+ +

Styles are passed as an object of property-value pairs in which the +properties are specified in their camelized form (e.g., fontSize).

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/show/index.html b/doc/1.6.1/dom/element/show/index.html new file mode 100644 index 000000000..7c15ae9e4 --- /dev/null +++ b/doc/1.6.1/dom/element/show/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.show + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.show +

+ + + + +
+
+
+
+
+
Element.show(element) → Element
+ + +

Removes display: none on element. Returns element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/siblings/index.html b/doc/1.6.1/dom/element/siblings/index.html new file mode 100644 index 000000000..7c5559a94 --- /dev/null +++ b/doc/1.6.1/dom/element/siblings/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.siblings + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.siblings +

+ + + + +
+
+
+
+
+
Element.siblings(element) → [Element…]
+ + +

Collects all of element's siblings and returns them as an array of +elements.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/stopobserving/index.html b/doc/1.6.1/dom/element/stopobserving/index.html new file mode 100644 index 000000000..ea7fdba01 --- /dev/null +++ b/doc/1.6.1/dom/element/stopobserving/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.stopObserving + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.stopObserving +

+ + + + +
+
+
+
+
+
Element.stopObserving(element[, eventName[, handler]]) → Element
+ + +

See Event.stopObserving.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/store/index.html b/doc/1.6.1/dom/element/store/index.html new file mode 100644 index 000000000..a001100fd --- /dev/null +++ b/doc/1.6.1/dom/element/store/index.html @@ -0,0 +1,271 @@ + + + + + Prototype v1.6.1 API documentation | Element.store + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.store +

+ + + + +
+
+
+
+
+
Element.store(element, key, value) → Element
+ + +

Stores a key/value pair of custom metadata on the element.

+ +

The metadata can later be retrieved with Element.retrieve.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/toggle/index.html b/doc/1.6.1/dom/element/toggle/index.html new file mode 100644 index 000000000..594d968de --- /dev/null +++ b/doc/1.6.1/dom/element/toggle/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.toggle + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.toggle +

+ + + + +
+
+
+
+
+
Element.toggle(element) → Element
+ + +

Toggles the visibility of element. Returns element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/toggleclassname/index.html b/doc/1.6.1/dom/element/toggleclassname/index.html new file mode 100644 index 000000000..9a9cb6e21 --- /dev/null +++ b/doc/1.6.1/dom/element/toggleclassname/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.6.1 API documentation | Element.toggleClassName + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.toggleClassName +

+ + + + +
+
+
+
+
+
Element.toggleClassName(element, className) → Element
+ + +

Toggles the presence of a CSS class on element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/undoclipping/index.html b/doc/1.6.1/dom/element/undoclipping/index.html new file mode 100644 index 000000000..203ec6997 --- /dev/null +++ b/doc/1.6.1/dom/element/undoclipping/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.undoClipping + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.undoClipping +

+ + + + +
+
+
+
+
+
Element.undoClipping(element) → Element
+ + +

Sets element's CSS overflow property back to the value it had +before Element.makeClipping was applied.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/undopositioned/index.html b/doc/1.6.1/dom/element/undopositioned/index.html new file mode 100644 index 000000000..b3cdd2ddc --- /dev/null +++ b/doc/1.6.1/dom/element/undopositioned/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.undoPositioned + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.undoPositioned +

+ + + + +
+
+
+
+
+
Element.undoPositioned(element) → Element
+ + +

Sets element back to the state it was in before +Element.makePositioned was applied to it.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/up/index.html b/doc/1.6.1/dom/element/up/index.html new file mode 100644 index 000000000..35382ce6d --- /dev/null +++ b/doc/1.6.1/dom/element/up/index.html @@ -0,0 +1,279 @@ + + + + + Prototype v1.6.1 API documentation | Element.up + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.up +

+ + + + +
+
+
+
+
+
Element.up(element[, expression[, index = 0]]) → Element
Element.up(element[, index = 0]) → Element
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Returns element's first ancestor (or the Nth ancestor, if index +is specified) that matches expression. If no expression is +provided, all ancestors are considered. If no ancestor matches these +criteria, undefined is returned.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/update/index.html b/doc/1.6.1/dom/element/update/index.html new file mode 100644 index 000000000..5d8c87d4c --- /dev/null +++ b/doc/1.6.1/dom/element/update/index.html @@ -0,0 +1,289 @@ + + + + + Prototype v1.6.1 API documentation | Element.update + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.update +

+ + + + +
+
+
+
+
+
Element.update(element[, newContent]) → Element
+ + +

Replaces the content of element with the newContent argument and +returns element.

+ +

newContent may be in any of these forms:

+ +
    +
  • String: A string of HTML to be parsed and rendered
  • +
  • Element: An Element instance to insert
  • +
  • ...any object with a toElement method: The method is called and the resulting element used
  • +
  • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
  • +
+ +

If newContent is omitted, the element's content is blanked out (i.e., +replaced with an empty string).

+ +

If newContent is a string and contains one or more inline <script> tags, the scripts +are scheduled to be evaluated after a very brief pause (using Function#defer) to allow +the browser to finish updating the DOM. Note that the scripts are evaluated +in the scope of String#evalScripts, not in the global scope, which has important +ramifications for your vars and functions. See String#evalScripts for details.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/viewportoffset/index.html b/doc/1.6.1/dom/element/viewportoffset/index.html new file mode 100644 index 000000000..2f9a5472e --- /dev/null +++ b/doc/1.6.1/dom/element/viewportoffset/index.html @@ -0,0 +1,272 @@ + + + + + Prototype v1.6.1 API documentation | Element.viewportOffset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.viewportOffset +

+ + + + +
+
+
+
+
+
Element.viewportOffset(element) → Array
+ + +

Returns the X/Y coordinates of element relative to the viewport.

+ +

Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/visible/index.html b/doc/1.6.1/dom/element/visible/index.html new file mode 100644 index 000000000..693a96617 --- /dev/null +++ b/doc/1.6.1/dom/element/visible/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.visible + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.visible +

+ + + + +
+
+
+
+
+
Element.visible(element) → boolean
+ + +

Tells whether element is visible (i.e., whether its inline display +CSS property is set to none.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/wrap/index.html b/doc/1.6.1/dom/element/wrap/index.html new file mode 100644 index 000000000..ba049ebb0 --- /dev/null +++ b/doc/1.6.1/dom/element/wrap/index.html @@ -0,0 +1,281 @@ + + + + + Prototype v1.6.1 API documentation | Element.wrap + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.wrap +

+ + + + +
+
+
+
+
+
Element.wrap(element, wrapper[, attributes]) → Element
+
    +
  • + wrapper + (Element | String) + – An element to wrap element inside, or else a string representing the tag name of an element to be created. +
  • +
  • + attributes + (Object) + – A set of attributes to apply to the wrapper element. Refer to the Element constructor for usage. +
  • +
+ + +

Wraps an element inside another, then returns the wrapper.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/element/writeattribute/index.html b/doc/1.6.1/dom/element/writeattribute/index.html new file mode 100644 index 000000000..a4fc792c9 --- /dev/null +++ b/doc/1.6.1/dom/element/writeattribute/index.html @@ -0,0 +1,270 @@ + + + + + Prototype v1.6.1 API documentation | Element.writeAttribute + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Element.writeAttribute +

+ + + + +
+
+
+
+
+
Element.writeAttribute(element, attribute[, value = true]) → Element
Element.writeAttribute(element, attributes) → Element
+ + +

Adds, changes, or removes attributes passed as either a hash or a +name/value pair.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/element/index.html b/doc/1.6.1/dom/event/element/index.html new file mode 100644 index 000000000..266ba53b3 --- /dev/null +++ b/doc/1.6.1/dom/event/element/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.6.1 API documentation | Event.element + + + + + + + + + + + + + + + + +
+ +
+ + +
Deprecated
+ + + +

src code

+ +

+ class method Event.element +

+ + + + +
+
+
+
+
+
Event.element(event) → Element
+ + +

Returns the DOM element on which the event occurred. This method +is deprecated, use findElement instead.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/findelement/index.html b/doc/1.6.1/dom/event/findelement/index.html new file mode 100644 index 000000000..b4ca83d37 --- /dev/null +++ b/doc/1.6.1/dom/event/findelement/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.6.1 API documentation | Event.findElement + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.findElement +

+ + + + +
+
+
+
+
+
Event.findElement(event, expression) → Element
+ + +

Returns the first DOM element that matches a given CSS selector — +starting with the element on which the event occurred, then moving up +its ancestor chain.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/fire/index.html b/doc/1.6.1/dom/event/fire/index.html new file mode 100644 index 000000000..7a4235b4d --- /dev/null +++ b/doc/1.6.1/dom/event/fire/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.6.1 API documentation | Event.fire + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.fire +

+ + + + +
+
+
+
+
+
Event.fire(element, eventName[, memo[, bubble = true]]) → Event
+
    +
  • + memo + (?) + – Metadata for the event. Will be accessible through the event's memo property. +
  • +
  • + bubble + (Boolean) + – Whether the event will bubble. +
  • +
+ + +

Fires a custom event of name eventName with element as its target.

+ +

Custom events must include a colon (:) in their names.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/index.html b/doc/1.6.1/dom/event/index.html new file mode 100644 index 000000000..899242913 --- /dev/null +++ b/doc/1.6.1/dom/event/index.html @@ -0,0 +1,245 @@ + + + + + Prototype v1.6.1 API documentation | Event + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Event +

+ + + + +
+
+

Description

+
+
+ +

The namespace for Prototype's event system.

+ +

Events: a fine mess

+ +

Event management is one of the really sore spots of cross-browser +scripting.

+ +

True, the prevalent issue is: everybody does it the W3C way, and MSIE +does it another way altogether. But there are quite a few subtler, +sneakier issues here and there waiting to bite your ankle — such as the +keypress/keydown issue with KHTML-based browsers (Konqueror and +Safari). Also, MSIE has a tendency to leak memory when it comes to +discarding event handlers.

+ +

Prototype to the rescue

+ +

Of course, Prototype smooths it over so well you'll forget these +troubles even exist. Enter the Event namespace. It is replete with +methods that help to normalize the information reported by events across +browsers.

+ +

Event also provides a standardized list of key codes you can use with +keyboard-related events.

+ +

The functions you're most likely to use a lot are Event.observe, +Event.element and Event.stop. If your web app uses custom events, +you'll also get a lot of mileage out of Event.fire.

+
+
+ + + + + + + + + + +
+
+

Class methods

+
+ +
+ +
+
+

Instance methods

+
+ +
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/isleftclick/index.html b/doc/1.6.1/dom/event/isleftclick/index.html new file mode 100644 index 000000000..ae8d6be32 --- /dev/null +++ b/doc/1.6.1/dom/event/isleftclick/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | Event.isLeftClick + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.isLeftClick +

+ + + + +
+
+
+
+
+
Event.isLeftClick(event) → Boolean
+ + +

Determines whether a button-related mouse event involved the left +mouse button.

+ +

Keep in mind that the "left" mouse button is actually the "primary" mouse +button. When a mouse is in left-handed mode, the browser will report +clicks of the right button as "left-clicks."

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/ismiddleclick/index.html b/doc/1.6.1/dom/event/ismiddleclick/index.html new file mode 100644 index 000000000..3a5525db3 --- /dev/null +++ b/doc/1.6.1/dom/event/ismiddleclick/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.6.1 API documentation | Event.isMiddleClick + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.isMiddleClick +

+ + + + +
+
+
+
+
+
Event.isMiddleClick(event) → Boolean
+ + +

Determines whether a button-related mouse event involved the middle +mouse button.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/isrightclick/index.html b/doc/1.6.1/dom/event/isrightclick/index.html new file mode 100644 index 000000000..801742a7e --- /dev/null +++ b/doc/1.6.1/dom/event/isrightclick/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | Event.isRightClick + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.isRightClick +

+ + + + +
+
+
+
+
+
Event.isRightClick(event) → Boolean
+ + +

Determines whether a button-related mouse event involved the right +mouse button.

+ +

Keep in mind that the "left" mouse button is actually the "secondary" +mouse button. When a mouse is in left-handed mode, the browser will +report clicks of the left button as "left-clicks."

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/observe/index.html b/doc/1.6.1/dom/event/observe/index.html new file mode 100644 index 000000000..e220788c8 --- /dev/null +++ b/doc/1.6.1/dom/event/observe/index.html @@ -0,0 +1,318 @@ + + + + + Prototype v1.6.1 API documentation | Event.observe + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.observe +

+ + + + +
+
+
+
+
+
Event.observe(element, eventName, handler) → Element
+
    +
  • + element + (Element | String) + – The DOM element to observe, or its ID. +
  • +
  • + eventName + (String) + – The name of the event, in all lower case, without the "on" prefix — e.g., "click" (not "onclick"). +
  • +
  • + handler + (Function) + – The function to call when the event occurs. +
  • +
+ + +

Registers an event handler on a DOM element. Aliased as Element#observe.

+ +

Event.observe smooths out a variety of differences between browsers and provides +some handy additional features as well. Key features in brief:

+ +
    +
  • Several handlers can be registered for the same event on the same element.
  • +
  • Prototype figures out whether to use addEventListener (W3C standard) or +attachEvent (MSIE); you don't have to worry about it.
  • +
  • The handler is passed an extended Event object (even on MSIE).
  • +
  • The handler's context (this value) is set to the extended element being observed +(even if the event actually occurred on a descendent element and bubbled up).
  • +
  • Prototype handles cleaning up the handler when leaving the page (important for MSIE memory +leak prevention).
  • +
  • observe makes it possible to stop observing the event easily via Event.stopObserving.
  • +
+ +

Although you can use Event.observe directly and there are times when that's the most +convenient or direct way, it's more common to use its alias Element#observe. These two +statements have the same effect:

+ +
Event.observe('foo', 'click', myHandler);
+$('foo').observe('click', myHandler);
+
+
+ +

The examples in this documentation use the Element#observe form.

+ +

The Handler

+ +

Signature:

+ +
function handler(event) {
+  // `this` = the element being observed
+}
+
+
+ +

So for example, this will turn the background of the element 'foo' blue when it's clicked:

+ +
$('foo').observe('click', function(event) {
+  this.setStyle({backgroundColor: 'blue'});
+});
+
+
+ +

Note that we used this to refer to the element, and that we received the event object +as a parameter (even on MSIE).

+ +

It's All About Timing

+ +

One of the most common errors trying to observe events is trying to do it before the element +exists in the DOM. Don't try to observe elements until after the +dom:loaded event or window load event has been fired.

+ +

Preventing the Default Event Action and Bubbling

+ +

If we want to stop the event (e.g., prevent its default action and stop it bubbling), we can +do so with the extended event object's Event#stop method:

+ +
$('foo').observe('click', function(event) {
+  event.stop();
+});
+
+
+ +

Finding the Element Where the Event Occurred

+ +

Since most events bubble from descendant elements up through the hierarchy until they're +handled, we can observe an event on a container rather than individual elements within the +container. This is sometimes called "event delegation". It's particularly handy for tables:

+ +
<table id='records'>
+  <thead>
+    <tr><th colspan='2'>No record clicked</th></tr>
+  </thead>
+  <tbody>
+    <tr data-recnum='1'><td>1</td><td>First record</td></tr>
+    <tr data-recnum='2'><td>2</td><td>Second record</td></tr>
+    <tr data-recnum='3'><td>3</td><td>Third record</td></tr>
+  </tbody>
+</table>
+
+
+ +

Instead of observing each cell or row, we can simply observe the table:

+ +
$('records').observe('click', function(event) {
+  var clickedRow;
+  clickedRow = event.findElement('tr');
+  if (clickedRow) {
+    this.down('th').update("You clicked record #" + clickedRow.readAttribute("data-recnum"));
+  }
+});
+
+
+ +

When any row in the table is clicked, we update the table's first header cell saying which +record was clicked. Event#findElement finds the row that was clicked, and this refers +to the table we were observing.

+ +

Stopping Observing the Event

+ +

If we don't need to observe the event anymore, we can stop observing it with +Event.stopObserving (aka Element#stopObserving).

+ +

Using an Instance Method as a Handler

+ +

If we want to use an instance method as a handler, we will probably want to use +Function#bind to set the handler's context; otherwise, the context will be lost and +this won't mean what we expect it to mean within the handler function. E.g.:

+ +
var MyClass = Class.create({
+  initialize: function(name, element) {
+    this.name = name;
+    element = $(element);
+    if (element) {
+      element.observe(this.handleClick.bind(this));
+    }
+  },
+  handleClick: function(event) {
+    alert("My name is " + this.name);
+  },
+});
+
+
+ +

Without the bind, when handleClick was triggered by the event, this wouldn't +refer to the instance and so the alert wouldn't show the name. Because we used bind, it +works correctly. See Function#bind for +details. There's also Function#bindAsEventListener, which is handy for certain very +specific situations. (Normally, bind is all you need.)

+ +

Side Notes

+ +

Although Prototype smooths out most of the differences between browsers, the fundamental +behavior of a browser implementation isn't changed. For example, the timing of the change +or blur events varies a bit from browser to browser.

+ +

Changes in 1.6.x

+ +

Prior to Prototype 1.6, observe supported a fourth argument (useCapture), a boolean that +indicated whether to use the browser's capturing phase or its bubbling phase. Since MSIE does +not support the capturing phase, we removed this argument from 1.6, lest it give users the +false impression that they can use the capturing phase in all browsers.

+ +

1.6 also introduced setting the this context to the element being observed, automatically +extending the Event object, and the Event#findElement method.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/pointer/index.html b/doc/1.6.1/dom/event/pointer/index.html new file mode 100644 index 000000000..dc52ba904 --- /dev/null +++ b/doc/1.6.1/dom/event/pointer/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | Event.pointer + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.pointer +

+ + + + +
+
+
+
+
+
Event.pointer(event) → Object
+ + +

Returns the absolute position of the pointer for a mouse event.

+ +

Returns an object in the form { x: Number, y: Number}.

+ +

Note that this position is absolute on the page, not on the +viewport.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/pointerx/index.html b/doc/1.6.1/dom/event/pointerx/index.html new file mode 100644 index 000000000..677ec75a1 --- /dev/null +++ b/doc/1.6.1/dom/event/pointerx/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.6.1 API documentation | Event.pointerX + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.pointerX +

+ + + + +
+
+
+
+
+
Event.pointerX(event) → Number
+ + +

Returns the absolute horizontal position of the pointer for a mouse +event.

+ +

Note that this position is absolute on the page, not on the +viewport.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/pointery/index.html b/doc/1.6.1/dom/event/pointery/index.html new file mode 100644 index 000000000..8df7e538d --- /dev/null +++ b/doc/1.6.1/dom/event/pointery/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.6.1 API documentation | Event.pointerY + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.pointerY +

+ + + + +
+
+
+
+
+
Event.pointerY(event) → Number
+ + +

Returns the absolute vertical position of the pointer for a mouse +event.

+ +

Note that this position is absolute on the page, not on the +viewport.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/element/index.html b/doc/1.6.1/dom/event/prototype/element/index.html new file mode 100644 index 000000000..a468503bd --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/element/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.6.1 API documentation | Event#element + + + + + + + + + + + + + + + + +
+ +
+ + +
Deprecated
+ + + +

src code

+ +

+ instance method Event#element +

+ + + + +
+
+
+
+
+
Event#element() → Element
+ + +

Returns the DOM element on which the event occurred. This method +is deprecated, use findElement instead.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/findelement/index.html b/doc/1.6.1/dom/event/prototype/findelement/index.html new file mode 100644 index 000000000..2113051d5 --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/findelement/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.6.1 API documentation | Event#findElement + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Event#findElement +

+ + + + +
+
+
+
+
+
Event#findElement(expression) → Element
+ + +

Returns the first DOM element that matches a given CSS selector — +starting with the element on which the event occurred, then moving up +its ancestor chain.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/isleftclick/index.html b/doc/1.6.1/dom/event/prototype/isleftclick/index.html new file mode 100644 index 000000000..015253fde --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/isleftclick/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | Event#isLeftClick + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Event#isLeftClick +

+ + + + +
+
+
+
+
+
Event#isLeftClick() → Boolean
+ + +

Determines whether a button-related mouse event involved the left +mouse button.

+ +

Keep in mind that the "left" mouse button is actually the "primary" mouse +button. When a mouse is in left-handed mode, the browser will report +clicks of the right button as "left-clicks."

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/ismiddleclick/index.html b/doc/1.6.1/dom/event/prototype/ismiddleclick/index.html new file mode 100644 index 000000000..8bc069285 --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/ismiddleclick/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.6.1 API documentation | Event#isMiddleClick + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Event#isMiddleClick +

+ + + + +
+
+
+
+
+
Event#isMiddleClick() → Boolean
+ + +

Determines whether a button-related mouse event involved the middle +mouse button.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/isrightclick/index.html b/doc/1.6.1/dom/event/prototype/isrightclick/index.html new file mode 100644 index 000000000..2f75f6de3 --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/isrightclick/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | Event#isRightClick + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Event#isRightClick +

+ + + + +
+
+
+
+
+
Event#isRightClick() → Boolean
+ + +

Determines whether a button-related mouse event involved the right +mouse button.

+ +

Keep in mind that the "left" mouse button is actually the "secondary" +mouse button. When a mouse is in left-handed mode, the browser will +report clicks of the left button as "left-clicks."

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/pointer/index.html b/doc/1.6.1/dom/event/prototype/pointer/index.html new file mode 100644 index 000000000..70dad5562 --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/pointer/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | Event#pointer + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Event#pointer +

+ + + + +
+
+
+
+
+
Event#pointer() → Object
+ + +

Returns the absolute position of the pointer for a mouse event.

+ +

Returns an object in the form { x: Number, y: Number}.

+ +

Note that this position is absolute on the page, not on the +viewport.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/pointerx/index.html b/doc/1.6.1/dom/event/prototype/pointerx/index.html new file mode 100644 index 000000000..5e43c226f --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/pointerx/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.6.1 API documentation | Event#pointerX + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Event#pointerX +

+ + + + +
+
+
+
+
+
Event#pointerX() → Number
+ + +

Returns the absolute horizontal position of the pointer for a mouse +event.

+ +

Note that this position is absolute on the page, not on the +viewport.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/pointery/index.html b/doc/1.6.1/dom/event/prototype/pointery/index.html new file mode 100644 index 000000000..98dc21cce --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/pointery/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.6.1 API documentation | Event#pointerY + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Event#pointerY +

+ + + + +
+
+
+
+
+
Event#pointerY() → Number
+ + +

Returns the absolute vertical position of the pointer for a mouse +event.

+ +

Note that this position is absolute on the page, not on the +viewport.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/prototype/stop/index.html b/doc/1.6.1/dom/event/prototype/stop/index.html new file mode 100644 index 000000000..a259b83ff --- /dev/null +++ b/doc/1.6.1/dom/event/prototype/stop/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.6.1 API documentation | Event#stop + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Event#stop +

+ + + + +
+
+
+
+
+
Event#stop() → undefined
+ + +

Stops the event's propagation and prevents its eventual default action +from being triggered.

+ +

Stopping an event also sets a stopped property on that event for +future inspection.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/stop/index.html b/doc/1.6.1/dom/event/stop/index.html new file mode 100644 index 000000000..5a1b63aee --- /dev/null +++ b/doc/1.6.1/dom/event/stop/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.6.1 API documentation | Event.stop + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.stop +

+ + + + +
+
+
+
+
+
Event.stop(event) → undefined
+ + +

Stops the event's propagation and prevents its eventual default action +from being triggered.

+ +

Stopping an event also sets a stopped property on that event for +future inspection.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/event/stopobserving/index.html b/doc/1.6.1/dom/event/stopobserving/index.html new file mode 100644 index 000000000..b92f3d0f2 --- /dev/null +++ b/doc/1.6.1/dom/event/stopobserving/index.html @@ -0,0 +1,233 @@ + + + + + Prototype v1.6.1 API documentation | Event.stopObserving + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Event.stopObserving +

+ + + + +
+
+
+
+
+
Event.stopObserving(element[, eventName[, handler]]) → Element
+
    +
  • + element + (Element | String) + – The element to stop observing, or its ID. +
  • +
  • + eventName + (String) + – (Optional) The name of the event to stop observing, in all lower case, without the "on" — e.g., "click" (not "onclick"). +
  • +
  • + handler + (Function) + – (Optional) The handler to remove; must be the exact same reference that was passed to Event.observe (see below.). +
  • +
+ + +

Unregisters one or more event handlers.

+ +

If handler is omitted, unregisters all event handlers on element +for that eventName. If eventName is also omitted, unregisters all +event handlers on element. (In each case, only affects handlers registered via Prototype.)

+ +

Examples

+ +

Assuming:

+ +
$('foo').observe('click', myHandler);
+
+
+ +

...we can stop observing using that handler like so:

+ +
$('foo').stopObserving('click', myHandler);
+
+
+ +

If we want to remove all 'click' handlers from 'foo', we leave off the handler argument:

+ +
$('foo').stopObserving('click');
+
+
+ +

If we want to remove all handlers for all events from 'foo' (perhaps we're about to remove +it from the DOM), we simply omit both the handler and the event name:

+ +
$('foo').stopObserving();
+
+
+ +

A Common Error

+ +

When using instance methods as observers, it's common to use Function#bind on them, e.g.:

+ +
$('foo').observe('click', this.handlerMethod.bind(this));
+
+
+ +

If you do that, this will not work to unregister the handler:

+ +
$('foo').stopObserving('click', this.handlerMethod.bind(this)); // <== WRONG
+
+
+ +

Function#bind returns a new function every time it's called, and so if you don't retain +the reference you used when observing, you can't unhook that function specifically. (You can +still unhook all handlers for an event, or all handlers on the element entirely.)

+ +

To do this, you need to keep a reference to the bound function:

+ +
this.boundHandlerMethod = this.handlerMethod.bind(this);
+$('foo').observe('click', this.boundHandlerMethod);
+
+
+ +

...and then to remove:

+ +
$('foo').stopObserving('click', this.boundHandlerMethod); // <== Right
+
+
+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/disable/index.html b/doc/1.6.1/dom/form/disable/index.html new file mode 100644 index 000000000..d1130026f --- /dev/null +++ b/doc/1.6.1/dom/form/disable/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Form.disable + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.disable +

+ + + + +
+
+
+
+
+
Form.disable(form) → Element
+ + +

Disables the form as a whole. Form controls will be visible but +uneditable.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/clear/index.html b/doc/1.6.1/dom/form/element/clear/index.html new file mode 100644 index 000000000..b2ee4f418 --- /dev/null +++ b/doc/1.6.1/dom/form/element/clear/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.clear + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.clear +

+ + + + +
+
+
+
+
+
Form.Element.clear(element) → Element
+ + +

Clears the contents of a text input. Returns the element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/disable/index.html b/doc/1.6.1/dom/form/element/disable/index.html new file mode 100644 index 000000000..59e507311 --- /dev/null +++ b/doc/1.6.1/dom/form/element/disable/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.disable + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.disable +

+ + + + +
+
+
+
+
+
Form.Element.disable(element) → Element
+ + +

Disables a form control, effectively preventing its value from changing +until it is enabled again.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/enable/index.html b/doc/1.6.1/dom/form/element/enable/index.html new file mode 100644 index 000000000..17e58536c --- /dev/null +++ b/doc/1.6.1/dom/form/element/enable/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.enable + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.enable +

+ + + + +
+
+
+
+
+
Form.Element.enable(element) → Element
+ + +

Enables a previously disabled form control.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/eventobserver/index.html b/doc/1.6.1/dom/form/element/eventobserver/index.html new file mode 100644 index 000000000..583c5e318 --- /dev/null +++ b/doc/1.6.1/dom/form/element/eventobserver/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.EventObserver + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Form.Element.EventObserver +

+ + + + + + + + + + + + + + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/focus/index.html b/doc/1.6.1/dom/form/element/focus/index.html new file mode 100644 index 000000000..d8f9aee5a --- /dev/null +++ b/doc/1.6.1/dom/form/element/focus/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.focus + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.focus +

+ + + + +
+
+
+
+
+
Form.Element.focus(element) → Element
+ + +

Gives keyboard focus to an element. Returns the element.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/getvalue/index.html b/doc/1.6.1/dom/form/element/getvalue/index.html new file mode 100644 index 000000000..7fe5c96d6 --- /dev/null +++ b/doc/1.6.1/dom/form/element/getvalue/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.getValue + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.getValue +

+ + + + +
+
+
+
+
+
Form.Element.getValue(element) → String | Array
+ + +

Returns the current value of a form control.

+ +

A string is returned for most controls; only multiple select boxes +return an array of values.

+ +

The global shortcut for this method is $F.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/index.html b/doc/1.6.1/dom/form/element/index.html new file mode 100644 index 000000000..008de28b4 --- /dev/null +++ b/doc/1.6.1/dom/form/element/index.html @@ -0,0 +1,268 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ namespace Form.Element +

+ + + + +
+
+

Description

+
+
+ +

Utilities for dealing with form controls in the DOM.

+ +

This is a collection of methods that assist in dealing with form controls. +They provide ways to focus, serialize, disable/enable or extract current +value from a specific control.

+ +

Note that nearly all these methods are available directly on input, +select, and textarea elements. Therefore, these are equivalent:

+ +
Form.Element.activate('myfield');
+$('myfield').activate();
+
+
+ +

Naturally, you should always prefer the shortest form suitable in a +situation. Most of these methods also return the element itself (as +indicated by the return type) for chainability.

+
+
+ + + +
+
+

Classes

+
+
+ + +
+
+ + + + + + + + +
+
+

Class methods

+
+
+ + +
+
+ +
+
+

Instance methods

+
+
+ + +
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/observer/index.html b/doc/1.6.1/dom/form/element/observer/index.html new file mode 100644 index 000000000..41a677dbe --- /dev/null +++ b/doc/1.6.1/dom/form/element/observer/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.Observer + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Form.Element.Observer +

+ + + + +
+
+

Description

+
+
+ +

An Abstract.TimedObserver subclass that watches for changes to a form field's value. +This triggers the callback when the form field's value (according to +Form.Element#getValue) changes. (Note that when the value actually changes can vary from +browser to browser, particularly with select boxes.)

+
+
+ + + + + + + + +
+
+

Constructor

+
+ +
+ + + + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/observer/new/index.html b/doc/1.6.1/dom/form/element/observer/new/index.html new file mode 100644 index 000000000..1f94f0807 --- /dev/null +++ b/doc/1.6.1/dom/form/element/observer/new/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.6.1 API documentation | new Form.Element.Observer + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ constructor new Form.Element.Observer +

+ + + + +
+
+
+
+
+
new(element, frequency, callback)
+
    +
  • + element + (String | Element) + – The form element to watch. Can be an element instance or an ID. +
  • +
  • + frequency + (Number) + – The frequency, in seconds — e.g., 0.33 to check for changes every third of a second. +
  • +
  • + callback + (Function) + – The callback to trigger when the value changes. +
  • +
+ + +

Creates a Form.Element.Observer.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/present/index.html b/doc/1.6.1/dom/form/element/present/index.html new file mode 100644 index 000000000..24983edbf --- /dev/null +++ b/doc/1.6.1/dom/form/element/present/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.present + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.present +

+ + + + +
+
+
+
+
+
Form.Element.present(element) → Element
+ + +

Returns true if a text input has contents, false otherwise.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/prototype/activate/index.html b/doc/1.6.1/dom/form/element/prototype/activate/index.html new file mode 100644 index 000000000..c10d4daa4 --- /dev/null +++ b/doc/1.6.1/dom/form/element/prototype/activate/index.html @@ -0,0 +1,152 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element#activate + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form.Element#activate +

+ + + + +
+
+
+
+
+
Form.Element#activate(element) → Element
+ + +

Gives focus to a form control and selects its contents if it is a text +input.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/prototype/clear/index.html b/doc/1.6.1/dom/form/element/prototype/clear/index.html new file mode 100644 index 000000000..b49283037 --- /dev/null +++ b/doc/1.6.1/dom/form/element/prototype/clear/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element#clear + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form.Element#clear +

+ + + + +
+
+
+
+
+
Form.Element#clear() → Element
+ + +

Clears the contents of a text input. Returns the element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/prototype/disable/index.html b/doc/1.6.1/dom/form/element/prototype/disable/index.html new file mode 100644 index 000000000..8780a8728 --- /dev/null +++ b/doc/1.6.1/dom/form/element/prototype/disable/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element#disable + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form.Element#disable +

+ + + + +
+
+
+
+
+
Form.Element#disable() → Element
+ + +

Disables a form control, effectively preventing its value from changing +until it is enabled again.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/prototype/enable/index.html b/doc/1.6.1/dom/form/element/prototype/enable/index.html new file mode 100644 index 000000000..72ffe2f3d --- /dev/null +++ b/doc/1.6.1/dom/form/element/prototype/enable/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element#enable + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form.Element#enable +

+ + + + +
+
+
+
+
+
Form.Element#enable() → Element
+ + +

Enables a previously disabled form control.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/prototype/getvalue/index.html b/doc/1.6.1/dom/form/element/prototype/getvalue/index.html new file mode 100644 index 000000000..f660b94f1 --- /dev/null +++ b/doc/1.6.1/dom/form/element/prototype/getvalue/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element#getValue + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form.Element#getValue +

+ + + + +
+
+
+
+
+
Form.Element#getValue() → String | Array
+ + +

Returns the current value of a form control.

+ +

A string is returned for most controls; only multiple select boxes +return an array of values.

+ +

The global shortcut for this method is $F.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/prototype/present/index.html b/doc/1.6.1/dom/form/element/prototype/present/index.html new file mode 100644 index 000000000..4d2860ef8 --- /dev/null +++ b/doc/1.6.1/dom/form/element/prototype/present/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element#present + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form.Element#present +

+ + + + +
+
+
+
+
+
Form.Element#present() → Element
+ + +

Returns true if a text input has contents, false otherwise.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/prototype/serialize/index.html b/doc/1.6.1/dom/form/element/prototype/serialize/index.html new file mode 100644 index 000000000..100127431 --- /dev/null +++ b/doc/1.6.1/dom/form/element/prototype/serialize/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element#serialize + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form.Element#serialize +

+ + + + +
+
+
+
+
+
Form.Element#serialize() → String
+ + +

Returns a URL-encoded string representation of a form control in the +name=value format.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/prototype/setvalue/index.html b/doc/1.6.1/dom/form/element/prototype/setvalue/index.html new file mode 100644 index 000000000..21c9583e3 --- /dev/null +++ b/doc/1.6.1/dom/form/element/prototype/setvalue/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element#setValue + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form.Element#setValue +

+ + + + +
+
+
+
+
+
Form.Element#setValue(value) → Element
+ + +

Sets value to be the value of the form control. Returns the element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/select/index.html b/doc/1.6.1/dom/form/element/select/index.html new file mode 100644 index 000000000..98e0f5aae --- /dev/null +++ b/doc/1.6.1/dom/form/element/select/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.select + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.select +

+ + + + +
+
+
+
+
+
Form.Element.select(element) → Element
+ + +

Selects the current text in a text input. Returns the element.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/serialize/index.html b/doc/1.6.1/dom/form/element/serialize/index.html new file mode 100644 index 000000000..de8825570 --- /dev/null +++ b/doc/1.6.1/dom/form/element/serialize/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.serialize + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.serialize +

+ + + + +
+
+
+
+
+
Form.Element.serialize(element) → String
+ + +

Returns a URL-encoded string representation of a form control in the +name=value format.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/element/setvalue/index.html b/doc/1.6.1/dom/form/element/setvalue/index.html new file mode 100644 index 000000000..9a8ef0a8a --- /dev/null +++ b/doc/1.6.1/dom/form/element/setvalue/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.Element.setValue + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.Element.setValue +

+ + + + +
+
+
+
+
+
Form.Element.setValue(element, value) → Element
+ + +

Sets value to be the value of the form control. Returns the element.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/enable/index.html b/doc/1.6.1/dom/form/enable/index.html new file mode 100644 index 000000000..f63267844 --- /dev/null +++ b/doc/1.6.1/dom/form/enable/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.enable + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.enable +

+ + + + +
+
+
+
+
+
Form.enable(form) → Element
+ + +

Enables a fully- or partially-disabled form.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/findfirstelement/index.html b/doc/1.6.1/dom/form/findfirstelement/index.html new file mode 100644 index 000000000..e212a6e08 --- /dev/null +++ b/doc/1.6.1/dom/form/findfirstelement/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.findFirstElement + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.findFirstElement +

+ + + + +
+
+
+
+
+
Form.findFirstElement(form) → Element
+ + +

Finds the first non-hidden, non-disabled control within the form.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/focusfirstelement/index.html b/doc/1.6.1/dom/form/focusfirstelement/index.html new file mode 100644 index 000000000..a4496ed55 --- /dev/null +++ b/doc/1.6.1/dom/form/focusfirstelement/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.focusFirstElement + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.focusFirstElement +

+ + + + +
+
+
+
+
+
Form.focusFirstElement(form) → Element
+ + +

Gives keyboard focus to the first element of the form. Returns the form.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/getelements/index.html b/doc/1.6.1/dom/form/getelements/index.html new file mode 100644 index 000000000..883abeb11 --- /dev/null +++ b/doc/1.6.1/dom/form/getelements/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form.getElements + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.getElements +

+ + + + +
+
+
+
+
+
Form.getElements(form) → [Element…]
+ + +

Returns a collection of all controls within a form.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/getinputs/index.html b/doc/1.6.1/dom/form/getinputs/index.html new file mode 100644 index 000000000..be9d3190a --- /dev/null +++ b/doc/1.6.1/dom/form/getinputs/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.6.1 API documentation | Form.getInputs + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.getInputs +

+ + + + +
+
+
+
+
+
Form.getInputs(form [, type [, name]]) → [Element…]
+
    +
  • + type + (String) + – A value for the type attribute against which to filter. +
  • +
  • + name + (String) + – A value for the name attribute against which to filter. +
  • +
+ + +

Returns a collection of all INPUT elements in a form.

+ +

Use optional type and name arguments to restrict the search on +these attributes.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/index.html b/doc/1.6.1/dom/form/index.html new file mode 100644 index 000000000..f02abd679 --- /dev/null +++ b/doc/1.6.1/dom/form/index.html @@ -0,0 +1,252 @@ + + + + + Prototype v1.6.1 API documentation | Form + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ namespace Form +

+ + + + +
+
+

Description

+
+
+ +

Utilities for dealing with forms in the DOM.

+ +

Form is a namespace for all things form-related, packed with form +manipulation and serialization goodness. While it holds methods dealing +with forms as a whole, its submodule Form.Element deals with specific +form controls.

+ +

Many of these methods are also available directly on form elements.

+
+
+ + +
+
+

Namespaces

+
+
+ +
    +
  • +

    Form.Element

    + +

    Utilities for dealing with form controls in the DOM.

    +
  • +
+
+
+ + +
+
+

Classes

+
+
+ +
    +
  • +

    Form.Observer

    + +

    An Abstract.TimedObserver subclass that watches for changes to a form. +The callback is triggered when the form changes — e.g., when any of its fields' values +changes, when fields are added/removed, etc.; anything that affects the serialized +form of the form (see Form#serialize).

    +
  • +
+
+
+ + + + + + + + +
+
+

Class methods

+
+ +
+ +
+
+

Instance methods

+
+ +
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/observer/index.html b/doc/1.6.1/dom/form/observer/index.html new file mode 100644 index 000000000..8b3739b19 --- /dev/null +++ b/doc/1.6.1/dom/form/observer/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Form.Observer + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Form.Observer +

+ + + + +
+
+

Description

+
+
+ +

An Abstract.TimedObserver subclass that watches for changes to a form. +The callback is triggered when the form changes — e.g., when any of its fields' values +changes, when fields are added/removed, etc.; anything that affects the serialized +form of the form (see Form#serialize).

+
+
+ + + + + + + + +
+
+

Constructor

+
+ +
+ + + + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/observer/new/index.html b/doc/1.6.1/dom/form/observer/new/index.html new file mode 100644 index 000000000..196ba71bd --- /dev/null +++ b/doc/1.6.1/dom/form/observer/new/index.html @@ -0,0 +1,152 @@ + + + + + Prototype v1.6.1 API documentation | new Form.Observer + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ constructor new Form.Observer +

+ + + + +
+
+
+
+
+
new(element, frequency, callback)
+
    +
  • + element + (String | Element) + – The element of the form to watch. Can be an element instance or an ID. +
  • +
  • + frequency + (Number) + – The frequency, in seconds -- e.g., 0.33 to check for changes every third of a second. +
  • +
  • + callback + (Function) + – The callback to trigger when the form changes. +
  • +
+ + +

Creates a Form.Observer.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/prototype/disable/index.html b/doc/1.6.1/dom/form/prototype/disable/index.html new file mode 100644 index 000000000..476455a99 --- /dev/null +++ b/doc/1.6.1/dom/form/prototype/disable/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Form#disable + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form#disable +

+ + + + +
+
+
+
+
+
Form#disable() → Element
+ + +

Disables the form as a whole. Form controls will be visible but +uneditable.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/prototype/enable/index.html b/doc/1.6.1/dom/form/prototype/enable/index.html new file mode 100644 index 000000000..74ed72ee2 --- /dev/null +++ b/doc/1.6.1/dom/form/prototype/enable/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form#enable + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form#enable +

+ + + + +
+
+
+
+
+
Form#enable() → Element
+ + +

Enables a fully- or partially-disabled form.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/prototype/findfirstelement/index.html b/doc/1.6.1/dom/form/prototype/findfirstelement/index.html new file mode 100644 index 000000000..b9ba424be --- /dev/null +++ b/doc/1.6.1/dom/form/prototype/findfirstelement/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form#findFirstElement + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form#findFirstElement +

+ + + + +
+
+
+
+
+
Form#findFirstElement() → Element
+ + +

Finds the first non-hidden, non-disabled control within the form.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/prototype/focusfirstelement/index.html b/doc/1.6.1/dom/form/prototype/focusfirstelement/index.html new file mode 100644 index 000000000..ead128d6e --- /dev/null +++ b/doc/1.6.1/dom/form/prototype/focusfirstelement/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form#focusFirstElement + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form#focusFirstElement +

+ + + + +
+
+
+
+
+
Form#focusFirstElement() → Element
+ + +

Gives keyboard focus to the first element of the form. Returns the form.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/prototype/getelements/index.html b/doc/1.6.1/dom/form/prototype/getelements/index.html new file mode 100644 index 000000000..f9efec7dc --- /dev/null +++ b/doc/1.6.1/dom/form/prototype/getelements/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Form#getElements + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form#getElements +

+ + + + +
+
+
+
+
+
Form#getElements() → [Element…]
+ + +

Returns a collection of all controls within a form.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/prototype/getinputs/index.html b/doc/1.6.1/dom/form/prototype/getinputs/index.html new file mode 100644 index 000000000..9717f45db --- /dev/null +++ b/doc/1.6.1/dom/form/prototype/getinputs/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.6.1 API documentation | Form#getInputs + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form#getInputs +

+ + + + +
+
+
+
+
+
Form#getInputs([type [, name]]) → [Element…]
+
    +
  • + type + (String) + – A value for the type attribute against which to filter. +
  • +
  • + name + (String) + – A value for the name attribute against which to filter. +
  • +
+ + +

Returns a collection of all INPUT elements in a form.

+ +

Use optional type and name arguments to restrict the search on +these attributes.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/prototype/request/index.html b/doc/1.6.1/dom/form/prototype/request/index.html new file mode 100644 index 000000000..0f2a36c87 --- /dev/null +++ b/doc/1.6.1/dom/form/prototype/request/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Form#request + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form#request +

+ + + + +
+
+
+
+
+
Form#request([options]) → Ajax.Request
+
    +
  • + options + (Object) + – Options to pass along to the Ajax.Request constructor. +
  • +
+ + +

A convenience method for serializing and submitting the form via an +Ajax.Request to the URL of the form's action attribute.

+ +

The options parameter is passed to the Ajax.Request instance, +allowing one to override the HTTP method and/or specify additional +parameters and callbacks.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/prototype/serialize/index.html b/doc/1.6.1/dom/form/prototype/serialize/index.html new file mode 100644 index 000000000..a64095ff5 --- /dev/null +++ b/doc/1.6.1/dom/form/prototype/serialize/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Form#serialize + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Form#serialize +

+ + + + +
+
+
+
+
+
Form#serialize([options]) → String | Object
+
    +
  • + options + (Object) + – A list of options that affect the return value of the method. +
  • +
+ + +

Serialize form data to an object or string suitable for Ajax requests.

+ +

See Form.serializeElements for details on the options.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/request/index.html b/doc/1.6.1/dom/form/request/index.html new file mode 100644 index 000000000..5bb545707 --- /dev/null +++ b/doc/1.6.1/dom/form/request/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Form.request + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.request +

+ + + + +
+
+
+
+
+
Form.request(form[, options]) → Ajax.Request
+
    +
  • + options + (Object) + – Options to pass along to the Ajax.Request constructor. +
  • +
+ + +

A convenience method for serializing and submitting the form via an +Ajax.Request to the URL of the form's action attribute.

+ +

The options parameter is passed to the Ajax.Request instance, +allowing one to override the HTTP method and/or specify additional +parameters and callbacks.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/reset/index.html b/doc/1.6.1/dom/form/reset/index.html new file mode 100644 index 000000000..68d9c8ab9 --- /dev/null +++ b/doc/1.6.1/dom/form/reset/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.6.1 API documentation | Form.reset + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.reset +

+ + + + +
+
+
+
+
+
Form.reset(form) → Element
+ + +

Resets a form to its default values.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/serialize/index.html b/doc/1.6.1/dom/form/serialize/index.html new file mode 100644 index 000000000..81fe6c6eb --- /dev/null +++ b/doc/1.6.1/dom/form/serialize/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Form.serialize + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.serialize +

+ + + + +
+
+
+
+
+
Form.serialize(form[, options]) → String | Object
+
    +
  • + options + (Object) + – A list of options that affect the return value of the method. +
  • +
+ + +

Serialize form data to an object or string suitable for Ajax requests.

+ +

See Form.serializeElements for details on the options.

+ + + + +

+ This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

+ +

+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/form/serializeelements/index.html b/doc/1.6.1/dom/form/serializeelements/index.html new file mode 100644 index 000000000..7cfdc55e0 --- /dev/null +++ b/doc/1.6.1/dom/form/serializeelements/index.html @@ -0,0 +1,204 @@ + + + + + Prototype v1.6.1 API documentation | Form.serializeElements + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Form.serializeElements +

+ + + + +
+
+
+
+
+
Form.serializeElements(elements[, options]) → String | Object
+
    +
  • + elements + (Array) + – A collection of elements to include in the serialization. +
  • +
  • + options + (Object) + – (Optional) A set of options that affect the return value of the method. +
  • +
+ + +

Serialize an array of form elements to an object or string suitable +for Ajax requests.

+ +

As per the HTML spec, disabled fields are not included.

+ +

If multiple elements have the same name and we're returning an object, +the value for that key in the object will be an array of the field values +in the order they appeared on the array of elements.

+ +

The Options

+ +

The options allow you to control two things: What kind of return +value you get (an object or a string), and whether and which submit +fields are included in that object or string.

+ +

If you do not supply an options object at all, the options +{hash: false} are used.

+ +

If you supply an options object, it may have the following options:

+ +
    +
  • hash (Boolean): true to return a plain object with keys and values +(not a Hash; see below), false to return a String in query string +format. If you supply an options object with no hash member, hash +defaults to true. Note that this is not the same as leaving off the +options object entirely (see above).
  • +
  • submit (Boolean | String): In essence: If you omit this option the +first submit button in the form is included; if you supply false, +no submit buttons are included; if you supply the name of a submit +button, the first button with that name is included. Note that the false +value must really be false, not falsey; falsey-but-not-false is +like omitting the option.
  • +
+ +

(Deprecated) If you pass in a Boolean instead of an object for options, it +is used as the hash option and all other options are defaulted.

+ +

A hash, not a Hash

+ +

If you opt to receive an object, it is a plain JavaScript object with keys +and values, not a Hash. All JavaScript objects are hashes in the lower-case +sense of the word, which is why the option has that somewhat-confusing name.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/index.html b/doc/1.6.1/dom/index.html new file mode 100644 index 000000000..356935843 --- /dev/null +++ b/doc/1.6.1/dom/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.6.1 API documentation | DOM section + + + + + + + + + + + + + + + + +
+ +
+ + + + + + +

+ section DOM section +

+ + + + +
+
+

Description

+
+
+ +

Extensions to DOM elements, plus other utilities for DOM traversal +and modification.

+ +

Prototype's DOM extensions represent a large portion of where you'll spend +your time. Prototype adds many convenience methods to elements returned by +the $ function. For instance, you can write

+ +
$('comments').addClassName('active').show();
+
+
+ +

to get the element with the ID of comments, add a class name to it, and +show it (if it was previously hidden).

+ +

In other words, Prototype adds "instance" methods to DOM nodes. This is +made possible by direct extension of the backing DOM objects (in browsers +that support it) and by manual extension of individual nodes (in browsers +that do not).

+
+
+ + + + +
+
+

Namespaces

+
+
+ +
    +
  • +

    document

    + +

    Prototype extends the built-in document object with several convenience +methods related to events.

    +
  • +
  • +

    Form

    + +

    Utilities for dealing with forms in the DOM.

    +
  • +
  • +

    Abstract

    + +
  • +
+
+
+ + +
+
+

Classes

+
+
+ +
    +
  • +

    Element

    + +
  • +
  • +

    Event

    + +

    The namespace for Prototype's event system.

    +
  • +
  • +

    Selector

    + +

    A class that queries the document for elements that match a given CSS +selector.

    +
  • +
+
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/selector/findchildelements/index.html b/doc/1.6.1/dom/selector/findchildelements/index.html new file mode 100644 index 000000000..c23daad09 --- /dev/null +++ b/doc/1.6.1/dom/selector/findchildelements/index.html @@ -0,0 +1,141 @@ + + + + + Prototype v1.6.1 API documentation | Selector.findChildElements + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Selector.findChildElements +

+ + + + +
+
+
+
+
+
Selector.findChildElements(element, expressions) → [Element…]
+ + +

Searches beneath element for any elements that match the selector +(or selectors) specified in expressions.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/selector/findelement/index.html b/doc/1.6.1/dom/selector/findelement/index.html new file mode 100644 index 000000000..d191d2d7c --- /dev/null +++ b/doc/1.6.1/dom/selector/findelement/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.6.1 API documentation | Selector.findElement + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Selector.findElement +

+ + + + +
+
+
+
+
+
Selector.findElement(elements, expression[, index = 0]) → Element
Selector.findElement(elements[, index = 0]) → Element
+ + +

Returns the indexth element in the collection that matches +expression.

+ +

Returns the indexth element overall if expression is not given.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/selector/index.html b/doc/1.6.1/dom/selector/index.html new file mode 100644 index 000000000..e3caf5546 --- /dev/null +++ b/doc/1.6.1/dom/selector/index.html @@ -0,0 +1,186 @@ + + + + + Prototype v1.6.1 API documentation | Selector + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class Selector +

+ + + + +
+
+

Description

+
+
+ +

A class that queries the document for elements that match a given CSS +selector.

+
+
+ + + + + + + + +
+
+

Constructor

+
+
+ +

new Selector

+
+
+ + + +
+
+

Class methods

+
+ +
+ +
+
+

Instance methods

+
+
+ + +
+
+ + +
+ + + +
+ + diff --git a/doc/1.6.1/dom/selector/matchelements/index.html b/doc/1.6.1/dom/selector/matchelements/index.html new file mode 100644 index 000000000..3d3afb517 --- /dev/null +++ b/doc/1.6.1/dom/selector/matchelements/index.html @@ -0,0 +1,142 @@ + + + + + Prototype v1.6.1 API documentation | Selector.matchElements + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Selector.matchElements +

+ + + + +
+
+
+
+
+
Selector.matchElements(elements, expression) → [Element…]
+ + +

Filters the given collection of elements with expression.

+ +

The only nodes returned will be those that match the given CSS selector.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/selector/new/index.html b/doc/1.6.1/dom/selector/new/index.html new file mode 100644 index 000000000..4341375ca --- /dev/null +++ b/doc/1.6.1/dom/selector/new/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | new Selector + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ constructor new Selector +

+ + + + +
+
+
+
+
+
new(expression)
+
    +
  • + expression + (String) + – A CSS selector. +
  • +
+ + +

Creates a Selector with the given CSS selector.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/selector/prototype/findelements/index.html b/doc/1.6.1/dom/selector/prototype/findelements/index.html new file mode 100644 index 000000000..65556f2b0 --- /dev/null +++ b/doc/1.6.1/dom/selector/prototype/findelements/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.6.1 API documentation | Selector#findElements + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Selector#findElements +

+ + + + +
+
+
+
+
+
Selector#findElements(root) → [Element…]
+ + +
    +
  • root (Element || document): A "scope" to search within. All results will +be descendants of this node.
  • +
+ +

Searches the document for elements that match the instance's CSS +selector.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/selector/prototype/match/index.html b/doc/1.6.1/dom/selector/prototype/match/index.html new file mode 100644 index 000000000..8735f805e --- /dev/null +++ b/doc/1.6.1/dom/selector/prototype/match/index.html @@ -0,0 +1,140 @@ + + + + + Prototype v1.6.1 API documentation | Selector#match + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ instance method Selector#match +

+ + + + +
+
+
+
+
+
Selector#match(element) → Boolean
+ + +

Tests whether a element matches the instance's CSS selector.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/dom/selector/split/index.html b/doc/1.6.1/dom/selector/split/index.html new file mode 100644 index 000000000..a3a94a4fa --- /dev/null +++ b/doc/1.6.1/dom/selector/split/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.6.1 API documentation | Selector.split + + + + + + + + + + + + + + + + +
+ +
+ + + + + +

src code

+ +

+ class method Selector.split +

+ + + + +
+
+
+
+
+
Selector.split(expression) → [String…]
+ + +

Takes a string of CSS selectors separated by commas; returns an array +of individual selectors.

+ +

Safer than doing a naive Array#split, since selectors can have commas +in other places.

+ + + + + +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/images/alias.png b/doc/1.6.1/images/alias.png new file mode 100755 index 000000000..6332fefea Binary files /dev/null and b/doc/1.6.1/images/alias.png differ diff --git a/doc/1.6.1/images/class.png b/doc/1.6.1/images/class.png new file mode 100644 index 000000000..e1510c169 Binary files /dev/null and b/doc/1.6.1/images/class.png differ diff --git a/doc/1.6.1/images/class_deprecated.png b/doc/1.6.1/images/class_deprecated.png new file mode 100644 index 000000000..9b7467990 Binary files /dev/null and b/doc/1.6.1/images/class_deprecated.png differ diff --git a/doc/1.6.1/images/class_method.png b/doc/1.6.1/images/class_method.png new file mode 100644 index 000000000..362e29562 Binary files /dev/null and b/doc/1.6.1/images/class_method.png differ diff --git a/doc/1.6.1/images/class_property.png b/doc/1.6.1/images/class_property.png new file mode 100755 index 000000000..ebaf0e874 Binary files /dev/null and b/doc/1.6.1/images/class_property.png differ diff --git a/doc/1.6.1/images/constant.png b/doc/1.6.1/images/constant.png new file mode 100644 index 000000000..c4295ec0d Binary files /dev/null and b/doc/1.6.1/images/constant.png differ diff --git a/doc/1.6.1/images/constructor.png b/doc/1.6.1/images/constructor.png new file mode 100755 index 000000000..565a9330e Binary files /dev/null and b/doc/1.6.1/images/constructor.png differ diff --git a/doc/1.6.1/images/deprecated.png b/doc/1.6.1/images/deprecated.png new file mode 100644 index 000000000..3f145ccce Binary files /dev/null and b/doc/1.6.1/images/deprecated.png differ diff --git a/doc/1.6.1/images/description.png b/doc/1.6.1/images/description.png new file mode 100755 index 000000000..5c870176d Binary files /dev/null and b/doc/1.6.1/images/description.png differ diff --git a/doc/1.6.1/images/grid.png b/doc/1.6.1/images/grid.png new file mode 100644 index 000000000..151ac265d Binary files /dev/null and b/doc/1.6.1/images/grid.png differ diff --git a/doc_assets/images/header-logo-small.png b/doc/1.6.1/images/header-logo-small.png similarity index 100% rename from doc_assets/images/header-logo-small.png rename to doc/1.6.1/images/header-logo-small.png diff --git a/doc/1.6.1/images/header-logo.png b/doc/1.6.1/images/header-logo.png new file mode 100644 index 000000000..4f6c7c186 Binary files /dev/null and b/doc/1.6.1/images/header-logo.png differ diff --git a/doc_assets/images/header-stripe-small.png b/doc/1.6.1/images/header-stripe-small.png similarity index 100% rename from doc_assets/images/header-stripe-small.png rename to doc/1.6.1/images/header-stripe-small.png diff --git a/doc/1.6.1/images/header-stripe.png b/doc/1.6.1/images/header-stripe.png new file mode 100644 index 000000000..2254f7c83 Binary files /dev/null and b/doc/1.6.1/images/header-stripe.png differ diff --git a/doc/1.6.1/images/information.png b/doc/1.6.1/images/information.png new file mode 100755 index 000000000..12cd1aef9 Binary files /dev/null and b/doc/1.6.1/images/information.png differ diff --git a/doc/1.6.1/images/instance_method.png b/doc/1.6.1/images/instance_method.png new file mode 100644 index 000000000..f6464ab43 Binary files /dev/null and b/doc/1.6.1/images/instance_method.png differ diff --git a/doc/1.6.1/images/instance_property.png b/doc/1.6.1/images/instance_property.png new file mode 100755 index 000000000..83ec984bd Binary files /dev/null and b/doc/1.6.1/images/instance_property.png differ diff --git a/doc/1.6.1/images/logo.png b/doc/1.6.1/images/logo.png new file mode 100644 index 000000000..6ff25884e Binary files /dev/null and b/doc/1.6.1/images/logo.png differ diff --git a/doc/1.6.1/images/menu-flap.png b/doc/1.6.1/images/menu-flap.png new file mode 100644 index 000000000..4424406b0 Binary files /dev/null and b/doc/1.6.1/images/menu-flap.png differ diff --git a/doc/1.6.1/images/method.png b/doc/1.6.1/images/method.png new file mode 100644 index 000000000..35efa7594 Binary files /dev/null and b/doc/1.6.1/images/method.png differ diff --git a/doc/1.6.1/images/method_deprecated.png b/doc/1.6.1/images/method_deprecated.png new file mode 100644 index 000000000..ee77e485f Binary files /dev/null and b/doc/1.6.1/images/method_deprecated.png differ diff --git a/doc/1.6.1/images/mixin.png b/doc/1.6.1/images/mixin.png new file mode 100644 index 000000000..11a7f8fed Binary files /dev/null and b/doc/1.6.1/images/mixin.png differ diff --git a/doc/1.6.1/images/namespace.png b/doc/1.6.1/images/namespace.png new file mode 100644 index 000000000..f2f7b73dd Binary files /dev/null and b/doc/1.6.1/images/namespace.png differ diff --git a/doc/1.6.1/images/property.png b/doc/1.6.1/images/property.png new file mode 100755 index 000000000..ebaf0e874 Binary files /dev/null and b/doc/1.6.1/images/property.png differ diff --git a/doc/1.6.1/images/related_to.png b/doc/1.6.1/images/related_to.png new file mode 100755 index 000000000..25eacb7c2 Binary files /dev/null and b/doc/1.6.1/images/related_to.png differ diff --git a/doc/1.6.1/images/search-background.png b/doc/1.6.1/images/search-background.png new file mode 100644 index 000000000..76295000a Binary files /dev/null and b/doc/1.6.1/images/search-background.png differ diff --git a/doc/1.6.1/images/section-background.png b/doc/1.6.1/images/section-background.png new file mode 100644 index 000000000..d3cf11e39 Binary files /dev/null and b/doc/1.6.1/images/section-background.png differ diff --git a/doc/1.6.1/images/section.png b/doc/1.6.1/images/section.png new file mode 100644 index 000000000..d9d598569 Binary files /dev/null and b/doc/1.6.1/images/section.png differ diff --git a/doc/1.6.1/images/subclass.png b/doc/1.6.1/images/subclass.png new file mode 100755 index 000000000..9ebf013a2 Binary files /dev/null and b/doc/1.6.1/images/subclass.png differ diff --git a/doc/1.6.1/images/superclass.png b/doc/1.6.1/images/superclass.png new file mode 100755 index 000000000..9ebf013a2 Binary files /dev/null and b/doc/1.6.1/images/superclass.png differ diff --git a/doc/1.6.1/images/tagline.png b/doc/1.6.1/images/tagline.png new file mode 100644 index 000000000..85b366caa Binary files /dev/null and b/doc/1.6.1/images/tagline.png differ diff --git a/doc/1.6.1/images/utility.png b/doc/1.6.1/images/utility.png new file mode 100755 index 000000000..59af16382 Binary files /dev/null and b/doc/1.6.1/images/utility.png differ diff --git a/doc/1.6.1/index.html b/doc/1.6.1/index.html new file mode 100644 index 000000000..07985d250 --- /dev/null +++ b/doc/1.6.1/index.html @@ -0,0 +1,208 @@ + + + + + Prototype v1.6.1 API documentation | Home + + + + + + + + + + + + + + + + +
+ + +
+ +
+

Prototype

+ +

An object-oriented JavaScript framework

+ +

Prototype is a JavaScript framework that aims to ease development of dynamic +web applications. It offers a familiar class-style OO framework, extensive +Ajax support, higher-order programming constructs, and easy DOM manipulation.

+ +

Targeted platforms

+ +

Prototype currently targets the following platforms:

+ +
    +
  • Microsoft Internet Explorer for Windows, version 6.0 and higher
  • +
  • Mozilla Firefox 1.5 and higher
  • +
  • Apple Safari 2.0.4 and higher
  • +
  • Opera 9.25 and higher
  • +
  • Chrome 1.0 and higher
  • +
+ +

Using Prototype

+ +

To use Prototype in your application, download the latest release from the +Prototype web site (http://prototypejs.org/download) and copy +dist/prototype.js to a suitable location. Then include it in your HTML +like so:

+ +
<script type="text/javascript" src="/path/to/prototype.js"></script>
+
+
+ +

Building Prototype from source

+ +

prototype.js is a composite file generated from many source files in +the src/ directory. To build Prototype, you'll need:

+ +
    +
  • a copy of the Prototype source tree, either from a distribution tarball or +from the Git repository (see below)
  • +
  • Ruby 1.8.2 or higher (http://www.ruby-lang.org/)
  • +
  • Rake--Ruby Make (http://rake.rubyforge.org/)
  • +
  • RDoc, if your Ruby distribution does not include it
  • +
+ +

From the root Prototype directory,

+ +
    +
  • rake dist will preprocess the Prototype source using Sprockets and +generate the composite dist/prototype.js.
  • +
  • rake package will create a distribution tarball in the +pkg/ directory.
  • +
+ +

Contributing to Prototype

+ +

Check out the Prototype source with

+ +
$ git clone git://github.com/sstephenson/prototype.git
+$ cd prototype
+$ git submodule init
+$ git submodule update vendor/sprockets vendor/pdoc vendor/unittest_js
+
+
+ +

Find out how to contribute: http://prototypejs.org/contribute.

+ +

Documentation

+ +

Please see the online Prototype API: http://prototypejs.org/api.

+
+ +
+
+

Sections

+
+
+ +
    +
  • +

    + Ajax +

    +

    Prototype's APIs around the XmlHttpRequest object.

    +
  • +
  • +

    + DOM +

    +

    Extensions to DOM elements, plus other utilities for DOM traversal +and modification.

    +
  • +
  • +

    + Language +

    +

    Additions to JavaScript's "standard library" and extensions to +built-in JavaScript objects.

    +
  • +
+
+
+ +
+ + + +
+ + diff --git a/doc/1.6.1/javascripts/application.js b/doc/1.6.1/javascripts/application.js new file mode 100644 index 000000000..a0303de26 --- /dev/null +++ b/doc/1.6.1/javascripts/application.js @@ -0,0 +1,478 @@ +//= require + +if (!Prototype || Prototype.Version.indexOf('1.6') !== 0) { + throw "This script requires Prototype >= 1.6."; +} + +Object.isDate = function(object) { + return object instanceof Date; +}; + +/** + * class Cookie + * Creates a cookie. +**/ +var Cookie = Class.create({ + /** + * new Cookie(name, value[, expires]) + * + * - name (String): The name of the cookie. + * - value (String): The value of the cookie. + * - expires (Number | Date): Exact date (or number of days from now) that + * the cookie will expire. + **/ + initialize: function(name, value, expires) { + expires = expires || ""; + if (Object.isNumber(expires)) { + var days = expires; + expires = new Date(); + expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000)); + } + + if (Object.isDate(expires)) + expires = expires.toGMTString(); + + if (!Object.isUndefined(expires) && expires !== "") + expires = "; expires=" + expires; + + this.name = name; + this.value = value; + this.expires = expires; + + document.cookie = name + "=" + value + expires + "; path=/"; + }, + + toString: function() { + return this.value; + }, + + inspect: function() { + return "#".interpolate(this); + } +}); + +/** + * Cookie +**/ +Object.extend(Cookie, { + /** + * Cookie.set(name, value, expires) + * + * Alias of [[Cookie#initialize]]. + **/ + set: function(name, value, expires) { + return new Cookie(name, value, expires); + }, + + /** + * Cookie.get(name) + * + * Returns the value of the cookie with the given name. + * - name (String): The name of the cookie to retrieve. + **/ + get: function(name) { + var c = document.cookie.split(';'); + + for (var i = 0, cookie; i < c.length; i++) { + cookie = c[i].split('='); + if (cookie[0].strip() === name) + return cookie[1].strip(); + } + + return null; + }, + + /** + * Cookie.unset(name) + * + * Deletes a cookie. + * - name (String): The name of the cookie to delete. + * + **/ + unset: function(name) { + return Cookie.set(name, "", -1); + } +}); + +Cookie.erase = Cookie.unset; + + + +if (typeof PDoc === 'undefined') { + window.PDoc = { + Sidebar: {} + }; +} + +// HISTORY MANAGER (sort of) +// Polls for changes to the hash. + +(function() { + var PREVIOUS_HASH = null; + + function poll() { + var hash = window.location.hash; + if (hash && hash !== PREVIOUS_HASH) { + document.fire('hash:changed', { + previous: PREVIOUS_HASH, current: hash + }); + } + PREVIOUS_HASH = hash; + window.setTimeout(arguments.callee, 100); + } + + Event.observe(window, 'load', poll); +})(); + +Object.extend(PDoc.Sidebar, { + getActiveTab: function() { + var activeTab = $('sidebar_tabs').down('.active'); + if (!activeTab) return null; + + var href = activeTab.readAttribute('href'); + return href.endsWith('menu_pane') ? 'menu_pane' : 'search_pane'; + }, + + // Remember the state of the sidebar so it can be restored on the next page. + serialize: function() { + var state = $H({ + activeTab: PDoc.Sidebar.getActiveTab(), + menuScrollOffset: $('menu_pane').scrollTop, + searchScrollOffset: $('search_results').scrollTop, + searchValue: $('search').getValue() + }); + + return escape(state.toJSON()); + }, + + // Restore the tree to a certain point based on a cookie. + restore: function(state) { + try { + state = unescape(state).evalJSON(); + var filterer = $('search').retrieve('filterer'); + filterer.setSearchValue(state.searchValue); + + (function() { + $('menu_pane').scrollTop = state.menuScrollOffset; + $('search_results').scrollTop = state.searchScrollOffset; + }).defer(); + } catch(error) { + console.log(error); + if (!(error instanceof SyntaxError)) throw error; + } + } +}); + + + +// Live API search. +PDoc.Sidebar.Filterer = Class.create({ + initialize: function(element, options) { + this.element = $(element); + this.options = Object.extend( + Object.clone(PDoc.Sidebar.Filterer.DEFAULT_OPTIONS), + options || {} + ); + + // The browser's "helpful" auto-complete gets in the way. + this.element.writeAttribute("autocomplete", "off"); + this.element.setValue(''); + + // Hitting "enter" should do nothing. + this.element.up('form').observe("submit", Event.stop); + + this.menu = this.options.menu; + this.links = this.menu.select('a'); + + this.resultsElement = this.options.resultsElement; + + this.observers = { + filter: this.filter.bind(this), + keydown: this.keydown.bind(this), + keyup: this.keyup.bind(this) + }; + + this.menu.setStyle({ opacity: 0.9 }); + this.addObservers(); + }, + + addObservers: function() { + this.element.observe('keyup', this.observers.filter); + }, + + // Called whenever the list of results needs to update as a result of a + // changed search key. + filter: function(event) { + // Clear the text box on ESC. + if (event.keyCode && event.keyCode === Event.KEY_ESC) { + this.element.setValue(''); + } + + if (PDoc.Sidebar.Filterer.INTERCEPT_KEYS.include(event.keyCode)) + return; + + // If there's nothing in the text box, clear the results list. + var value = $F(this.element).strip().toLowerCase(); + if (value === '') { + this.emptyResults(); + this.hideResults(); + return; + } + + var urls = this.findURLs(value); + this.buildResults(urls); + }, + + setSearchValue: function(value) { + this.element.setValue(value); + if (value.strip() === "") { + PDoc.Sidebar.Tabs.setActiveTab(0); + return; + } + this.buildResults(this.findURLs(value)); + }, + + // Given a key, finds all the PDoc objects that match. + findURLs: function(str) { + var results = []; + for (var name in PDoc.elements) { + if (name.toLowerCase().include(str.toLowerCase())) + results.push(PDoc.elements[name]); + } + return results; + }, + + buildResults: function(results) { + this.emptyResults(); + + results.each( function(result) { + var li = this._buildResult(result); + this.resultsElement.appendChild(li); + }, this); + this.showResults(); + }, + + _buildResult: function(obj) { + var li = new Element('li', { 'class': 'menu-item' }); + var a = new Element('a', { + 'class': obj.type.gsub(/\s/, '-'), + 'href': PDoc.pathPrefix + obj.path + }).update(obj.name); + + li.appendChild(a); + return li; + }, + + emptyResults: function() { + this.resultsElement.update(); + }, + + hideResults: function() { + PDoc.Sidebar.Tabs.setActiveTab(0); + //this.resultsElement.hide(); + document.stopObserving('keydown', this.observers.keydown); + document.stopObserving('keyup', this.observers.keyup); + }, + + showResults: function() { + PDoc.Sidebar.Tabs.setActiveTab(1); + //this.resultsElement.show(); + document.stopObserving('keydown', this.observers.keydown); + this.element.stopObserving('keyup', this.observers.keyup); + this.element.observe('keydown', this.observers.keydown); + document.observe('keyup', this.observers.keyup); + }, + + keydown: function(event) { + if (!PDoc.Sidebar.Filterer.INTERCEPT_KEYS.include(event.keyCode)) + return; + + // Also ignore if any modifier keys are present. + if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) + return; + + event.stop(); + + if (event.keyCode === Event.KEY_RETURN) { + // Follow the highlighted item, unless there is none. + if (!this.highlighted) return; + var a = this.highlighted.down('a'); + if (a) { + window.location.href = a.href; + } + } else if ([Event.KEY_UP, Event.KEY_DOWN].include(event.keyCode)) { + // Is an arrow key. + var direction = (Event.KEY_DOWN === event.keyCode) ? 1 : -1; + this.highlighted = this.moveHighlight(direction); + + if (!Prototype.Browser.WebKit) { + // If up/down key is held down, list should keep scrolling. + // WebKit does this automatically because it fires the keydown + // event over and over. + this._scrollTimer = window.setTimeout( + this.scrollList.bind(this, direction), 1000); + } + } + }, + + keyup: function(event) { + if (this._scrollTimer) { + window.clearTimeout(this._scrollTimer); + } + }, + + moveHighlight: function(direction) { + if (!this.highlighted) { + // If there is none, highlight the first result. + this.highlighted = + this.resultsElement.down('li').addClassName('highlighted'); + } else { + var method = (direction === 1) ? 'next' : 'previous'; + this.highlighted.removeClassName('highlighted'); + var adjacent = this.highlighted[method]('li'); + // If there isn't an adjacent one, we're at the top or bottom + // of the list. Flip it. + if (!adjacent) { + adjacent = method == 'next' ? this.resultsElement.down('li') : + this.resultsElement.down('li:last-of-type'); + } + adjacent.addClassName('highlighted'); + this.highlighted = adjacent; + } + + var h = this.highlighted, r = this.resultsElement; + + var distanceToBottom = h.offsetTop + h.offsetHeight; + if (distanceToBottom > (r.offsetHeight + r.scrollTop)) { + // Item is below the visible frame. + r.scrollTop = distanceToBottom - r.offsetHeight; + } else if (h.offsetTop < r.scrollTop) { + // Item is above the visible frame. + r.scrollTop = h.offsetTop; + } + + return this.highlighted; + }, + + scrollList: function(direction) { + this.moveHighlight(direction); + this._scrollTimer = window.setTimeout( + this.scrollList.bind(this, direction), 100); + } +}); + +Object.extend(PDoc.Sidebar.Filterer, { + INTERCEPT_KEYS: [Event.KEY_UP, Event.KEY_DOWN, Event.KEY_RETURN], + DEFAULT_OPTIONS: { + interval: 0.1, + resultsElement: '.search-results' + } +}); + + +Form.GhostedField = Class.create({ + initialize: function(element, title, options) { + options = options || {}; + + this.element = $(element); + this.title = title; + + this.isGhosted = true; + + if (options.cloak) { + + // Wrap the native getValue function so that it never returns the + // ghosted value. This is optional because it presumes the ghosted + // value isn't valid input for the field. + this.element.getValue = this.element.getValue.wrap(this.wrappedGetValue.bind(this)); + } + + this.addObservers(); + + this.onBlur(); + }, + + wrappedGetValue: function($proceed) { + var value = $proceed(); + return value === this.title ? "" : value; + }, + + addObservers: function() { + this.element.observe('focus', this.onFocus.bind(this)); + this.element.observe('blur', this.onBlur.bind(this)); + + var form = this.element.up('form'); + if (form) { + form.observe('submit', this.onSubmit.bind(this)); + } + + // Firefox's bfcache means that form fields need to be re-initialized + // when you hit the "back" button to return to the page. + if (Prototype.Browser.Gecko) { + window.addEventListener('pageshow', this.onBlur.bind(this), false); + } + }, + + onFocus: function() { + if (this.isGhosted) { + this.element.setValue(''); + this.setGhosted(false); + } + }, + + onBlur: function() { + var value = this.element.getValue(); + if (value.blank() || value == this.title) { + this.setGhosted(true); + } else { + this.setGhosted(false); + } + }, + + setGhosted: function(isGhosted) { + this.isGhosted = isGhosted; + this.element[isGhosted ? 'addClassName' : 'removeClassName']('ghosted'); + if (isGhosted) { + this.element.setValue(this.title); + } + }, + + // Hook into the enclosing form's `onsubmit` event so that we clear any + // ghosted text before the form is sent. + onSubmit: function() { + if (this.isGhosted) { + this.element.setValue(''); + } + } +}); + +document.observe('dom:loaded', function() { + PDoc.Sidebar.Tabs = new Control.Tabs($('sidebar_tabs')); + + var searchField = $('search'); + + if (searchField) { + var filterer = new PDoc.Sidebar.Filterer(searchField, { + menu: $('api_menu'), + resultsElement: $('search_results') + }); + searchField.store('filterer', filterer); + } + + // Prevent horizontal scrolling in scrollable sidebar areas. + $$('.scrollable').invoke('observe', 'scroll', function() { + this.scrollLeft = 0; + }); + + var sidebarState = Cookie.get('sidebar_state'); + if (sidebarState) { + PDoc.Sidebar.restore(sidebarState); + } + + new Form.GhostedField(searchField, searchField.getAttribute('title'), + { cloak: true }); +}); + +Event.observe(window, 'unload', function() { + Cookie.set('sidebar_state', PDoc.Sidebar.serialize()); +}); \ No newline at end of file diff --git a/doc/1.6.1/javascripts/controls.js b/doc/1.6.1/javascripts/controls.js new file mode 100644 index 000000000..fbc4418b8 --- /dev/null +++ b/doc/1.6.1/javascripts/controls.js @@ -0,0 +1,963 @@ +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) +// Contributors: +// Richard Livsey +// Rahul Bhargava +// Rob Wills +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// Autocompleter.Base handles all the autocompletion functionality +// that's independent of the data source for autocompletion. This +// includes drawing the autocompletion menu, observing keyboard +// and mouse events, and similar. +// +// Specific autocompleters need to provide, at the very least, +// a getUpdatedChoices function that will be invoked every time +// the text inside the monitored textbox changes. This method +// should get the text for which to provide autocompletion by +// invoking this.getToken(), NOT by directly accessing +// this.element.value. This is to allow incremental tokenized +// autocompletion. Specific auto-completion logic (AJAX, etc) +// belongs in getUpdatedChoices. +// +// Tokenized incremental autocompletion is enabled automatically +// when an autocompleter is instantiated with the 'tokens' option +// in the options parameter, e.g.: +// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); +// will incrementally autocomplete with a comma as the token. +// Additionally, ',' in the above example can be replaced with +// a token array, e.g. { tokens: [',', '\n'] } which +// enables autocompletion on multiple tokens. This is most +// useful when one of the tokens is \n (a newline), as it +// allows smart autocompletion after linebreaks. + +if(typeof Effect == 'undefined') + throw("controls.js requires including script.aculo.us' effects.js library"); + +var Autocompleter = { } +Autocompleter.Base = Class.create({ + baseInitialize: function(element, update, options) { + element = $(element) + this.element = element; + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; + this.entryCount = 0; + this.oldElementValue = this.element.value; + + if(this.setOptions) + this.setOptions(options); + else + this.options = options || { }; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || + function(element, update){ + if(!update.style.position || update.style.position=='absolute') { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update,{duration:0.15}); + }; + this.options.onHide = this.options.onHide || + function(element, update){ new Effect.Fade(update,{duration:0.15}) }; + + if(typeof(this.options.tokens) == 'string') + this.options.tokens = new Array(this.options.tokens); + // Force carriage returns as token delimiters anyway + if (!this.options.tokens.include('\n')) + this.options.tokens.push('\n'); + + this.observer = null; + + this.element.setAttribute('autocomplete','off'); + + Element.hide(this.update); + + Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() { + if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); + if(!this.iefix && + (Prototype.Browser.IE) && + (Element.getStyle(this.update, 'position')=='absolute')) { + new Insertion.After(this.update, + ''); + this.iefix = $(this.update.id+'_iefix'); + } + if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() { + this.stopIndicator(); + if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); + if(this.iefix) Element.hide(this.iefix); + }, + + startIndicator: function() { + if(this.options.indicator) Element.show(this.options.indicator); + }, + + stopIndicator: function() { + if(this.options.indicator) Element.hide(this.options.indicator); + }, + + onKeyPress: function(event) { + if(this.active) + switch(event.keyCode) { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + Event.stop(event); + return; + } + else + if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; + + this.changed = true; + this.hasFocus = true; + + if(this.observer) clearTimeout(this.observer); + this.observer = + setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); + }, + + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function(event) { + var element = Event.findElement(event, 'LI'); + if(this.index != element.autocompleteIndex) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function(event) { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; + this.selectEntry(); + this.hide(); + }, + + onBlur: function(event) { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() { + if(this.entryCount > 0) { + for (var i = 0; i < this.entryCount; i++) + this.index==i ? + Element.addClassName(this.getEntry(i),"selected") : + Element.removeClassName(this.getEntry(i),"selected"); + if(this.hasFocus) { + this.show(); + this.active = true; + } + } else { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() { + if(this.index > 0) this.index-- + else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() { + if(this.index < this.entryCount-1) this.index++ + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function(index) { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() { + return this.getEntry(this.index); + }, + + selectEntry: function() { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function(selectedElement) { + if (this.options.updateElement) { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if (this.options.select) { + var nodes = $(selectedElement).select('.' + this.options.select) || []; + if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); + } else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var bounds = this.getTokenBounds(); + if (bounds[0] != -1) { + var newValue = this.element.value.substr(0, bounds[0]); + var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); + if (whitespace) + newValue += whitespace[0]; + this.element.value = newValue + value + this.element.value.substr(bounds[1]); + } else { + this.element.value = value; + } + this.oldElementValue = this.element.value; + this.element.focus(); + + if (this.options.afterUpdateElement) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function(choices) { + if(!this.changed && this.hasFocus) { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.down()); + + if(this.update.firstChild && this.update.down().childNodes) { + this.entryCount = + this.update.down().childNodes.length; + for (var i = 0; i < this.entryCount; i++) { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } else { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if(this.entryCount==1 && this.options.autoSelect) { + this.selectEntry(); + this.hide(); + } else { + this.render(); + } + } + }, + + addObservers: function(element) { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() { + this.changed = false; + this.tokenBounds = null; + if(this.getToken().length>=this.options.minChars) { + this.getUpdatedChoices(); + } else { + this.active = false; + this.hide(); + } + this.oldElementValue = this.element.value; + }, + + getToken: function() { + var bounds = this.getTokenBounds(); + return this.element.value.substring(bounds[0], bounds[1]).strip(); + }, + + getTokenBounds: function() { + if (null != this.tokenBounds) return this.tokenBounds; + var value = this.element.value; + if (value.strip().empty()) return [-1, 0]; + var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); + var offset = (diff == this.oldElementValue.length ? 1 : 0); + var prevTokenPos = -1, nextTokenPos = value.length; + var tp; + for (var index = 0, l = this.options.tokens.length; index < l; ++index) { + tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); + if (tp > prevTokenPos) prevTokenPos = tp; + tp = value.indexOf(this.options.tokens[index], diff + offset); + if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; + } + return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); + } +}); + +Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { + var boundary = Math.min(newS.length, oldS.length); + for (var index = 0; index < boundary; ++index) + if (newS[index] != oldS[index]) + return index; + return boundary; +}; + +Ajax.Autocompleter = Class.create(Autocompleter.Base, { + initialize: function(element, update, url, options) { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() { + this.startIndicator(); + + var entry = encodeURIComponent(this.options.paramName) + '=' + + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? + this.options.callback(this.element, entry) : entry; + + if(this.options.defaultParams) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function(request) { + this.updateChoices(request.responseText); + } +}); + +// The local array autocompleter. Used when you'd prefer to +// inject an array of autocompletion options into the page, rather +// than sending out Ajax queries, which can be quite slow sometimes. +// +// The constructor takes four parameters. The first two are, as usual, +// the id of the monitored textbox, and id of the autocompletion menu. +// The third is the array you want to autocomplete from, and the fourth +// is the options block. +// +// Extra local autocompletion options: +// - choices - How many autocompletion choices to offer +// +// - partialSearch - If false, the autocompleter will match entered +// text only at the beginning of strings in the +// autocomplete array. Defaults to true, which will +// match text at the beginning of any *word* in the +// strings in the autocomplete array. If you want to +// search anywhere in the string, additionally set +// the option fullSearch to true (default: off). +// +// - fullSsearch - Search anywhere in autocomplete array strings. +// +// - partialChars - How many characters to enter before triggering +// a partial match (unlike minChars, which defines +// how many characters are required to do any match +// at all). Defaults to 2. +// +// - ignoreCase - Whether to ignore case when autocompleting. +// Defaults to true. +// +// It's possible to pass in a custom function as the 'selector' +// option, if you prefer to write your own autocompletion logic. +// In that case, the other options above will not apply unless +// you support them. + +Autocompleter.Local = Class.create(Autocompleter.Base, { + initialize: function(element, update, array, options) { + this.baseInitialize(element, update, options); + this.options.array = array; + }, + + getUpdatedChoices: function() { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function(options) { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function(instance) { + var ret = []; // Beginning matches + var partial = []; // Inside matches + var entry = instance.getToken(); + var count = 0; + + for (var i = 0; i < instance.options.array.length && + ret.length < instance.options.choices ; i++) { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase()) : + elem.indexOf(entry); + + while (foundPos != -1) { + if (foundPos == 0 && elem.length != entry.length) { + ret.push("
  • " + elem.substr(0, entry.length) + "" + + elem.substr(entry.length) + "
  • "); + break; + } else if (entry.length >= instance.options.partialChars && + instance.options.partialSearch && foundPos != -1) { + if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { + partial.push("
  • " + elem.substr(0, foundPos) + "" + + elem.substr(foundPos, entry.length) + "" + elem.substr( + foundPos + entry.length) + "
  • "); + break; + } + } + + foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : + elem.indexOf(entry, foundPos + 1); + + } + } + if (partial.length) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) + return "
      " + ret.join('') + "
    "; + } + }, options || { }); + } +}); + +// AJAX in-place editor and collection editor +// Full rewrite by Christophe Porteneuve (April 2007). + +// Use this if you notice weird scrolling problems on some browsers, +// the DOM might be a bit confused when this gets called so do this +// waits 1 ms (with setTimeout) until it does the activation +Field.scrollFreeActivate = function(field) { + setTimeout(function() { + Field.activate(field); + }, 1); +} + +Ajax.InPlaceEditor = Class.create({ + initialize: function(element, url, options) { + this.url = url; + this.element = element = $(element); + this.prepareOptions(); + this._controls = { }; + arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! + Object.extend(this.options, options || { }); + if (!this.options.formId && this.element.id) { + this.options.formId = this.element.id + '-inplaceeditor'; + if ($(this.options.formId)) + this.options.formId = ''; + } + if (this.options.externalControl) + this.options.externalControl = $(this.options.externalControl); + if (!this.options.externalControl) + this.options.externalControlOnly = false; + this._originalBackground = this.element.getStyle('background-color') || 'transparent'; + this.element.title = this.options.clickToEditText; + this._boundCancelHandler = this.handleFormCancellation.bind(this); + this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); + this._boundFailureHandler = this.handleAJAXFailure.bind(this); + this._boundSubmitHandler = this.handleFormSubmission.bind(this); + this._boundWrapperHandler = this.wrapUp.bind(this); + this.registerListeners(); + }, + checkForEscapeOrReturn: function(e) { + if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; + if (Event.KEY_ESC == e.keyCode) + this.handleFormCancellation(e); + else if (Event.KEY_RETURN == e.keyCode) + this.handleFormSubmission(e); + }, + createControl: function(mode, handler, extraClasses) { + var control = this.options[mode + 'Control']; + var text = this.options[mode + 'Text']; + if ('button' == control) { + var btn = document.createElement('input'); + btn.type = 'submit'; + btn.value = text; + btn.className = 'editor_' + mode + '_button'; + if ('cancel' == mode) + btn.onclick = this._boundCancelHandler; + this._form.appendChild(btn); + this._controls[mode] = btn; + } else if ('link' == control) { + var link = document.createElement('a'); + link.href = '#'; + link.appendChild(document.createTextNode(text)); + link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; + link.className = 'editor_' + mode + '_link'; + if (extraClasses) + link.className += ' ' + extraClasses; + this._form.appendChild(link); + this._controls[mode] = link; + } + }, + createEditField: function() { + var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); + var fld; + if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { + fld = document.createElement('input'); + fld.type = 'text'; + var size = this.options.size || this.options.cols || 0; + if (0 < size) fld.size = size; + } else { + fld = document.createElement('textarea'); + fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); + fld.cols = this.options.cols || 40; + } + fld.name = this.options.paramName; + fld.value = text; // No HTML breaks conversion anymore + fld.className = 'editor_field'; + if (this.options.submitOnBlur) + fld.onblur = this._boundSubmitHandler; + this._controls.editor = fld; + if (this.options.loadTextURL) + this.loadExternalText(); + this._form.appendChild(this._controls.editor); + }, + createForm: function() { + var ipe = this; + function addText(mode, condition) { + var text = ipe.options['text' + mode + 'Controls']; + if (!text || condition === false) return; + ipe._form.appendChild(document.createTextNode(text)); + }; + this._form = $(document.createElement('form')); + this._form.id = this.options.formId; + this._form.addClassName(this.options.formClassName); + this._form.onsubmit = this._boundSubmitHandler; + this.createEditField(); + if ('textarea' == this._controls.editor.tagName.toLowerCase()) + this._form.appendChild(document.createElement('br')); + if (this.options.onFormCustomization) + this.options.onFormCustomization(this, this._form); + addText('Before', this.options.okControl || this.options.cancelControl); + this.createControl('ok', this._boundSubmitHandler); + addText('Between', this.options.okControl && this.options.cancelControl); + this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); + addText('After', this.options.okControl || this.options.cancelControl); + }, + destroy: function() { + if (this._oldInnerHTML) + this.element.innerHTML = this._oldInnerHTML; + this.leaveEditMode(); + this.unregisterListeners(); + }, + enterEditMode: function(e) { + if (this._saving || this._editing) return; + this._editing = true; + this.triggerCallback('onEnterEditMode'); + if (this.options.externalControl) + this.options.externalControl.hide(); + this.element.hide(); + this.createForm(); + this.element.parentNode.insertBefore(this._form, this.element); + if (!this.options.loadTextURL) + this.postProcessEditField(); + if (e) Event.stop(e); + }, + enterHover: function(e) { + if (this.options.hoverClassName) + this.element.addClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onEnterHover'); + }, + getText: function() { + return this.element.innerHTML; + }, + handleAJAXFailure: function(transport) { + this.triggerCallback('onFailure', transport); + if (this._oldInnerHTML) { + this.element.innerHTML = this._oldInnerHTML; + this._oldInnerHTML = null; + } + }, + handleFormCancellation: function(e) { + this.wrapUp(); + if (e) Event.stop(e); + }, + handleFormSubmission: function(e) { + var form = this._form; + var value = $F(this._controls.editor); + this.prepareSubmission(); + var params = this.options.callback(form, value) || ''; + if (Object.isString(params)) + params = params.toQueryParams(); + params.editorId = this.element.id; + if (this.options.htmlResponse) { + var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Updater({ success: this.element }, this.url, options); + } else { + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.url, options); + } + if (e) Event.stop(e); + }, + leaveEditMode: function() { + this.element.removeClassName(this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + if (this.options.externalControl) + this.options.externalControl.show(); + this._saving = false; + this._editing = false; + this._oldInnerHTML = null; + this.triggerCallback('onLeaveEditMode'); + }, + leaveHover: function(e) { + if (this.options.hoverClassName) + this.element.removeClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onLeaveHover'); + }, + loadExternalText: function() { + this._form.addClassName(this.options.loadingClassName); + this._controls.editor.disabled = true; + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._form.removeClassName(this.options.loadingClassName); + var text = transport.responseText; + if (this.options.stripLoadedTextTags) + text = text.stripTags(); + this._controls.editor.value = text; + this._controls.editor.disabled = false; + this.postProcessEditField(); + }.bind(this), + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + postProcessEditField: function() { + var fpc = this.options.fieldPostCreation; + if (fpc) + $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); + }, + prepareOptions: function() { + this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); + Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); + [this._extraDefaultOptions].flatten().compact().each(function(defs) { + Object.extend(this.options, defs); + }.bind(this)); + }, + prepareSubmission: function() { + this._saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + registerListeners: function() { + this._listeners = { }; + var listener; + $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { + listener = this[pair.value].bind(this); + this._listeners[pair.key] = listener; + if (!this.options.externalControlOnly) + this.element.observe(pair.key, listener); + if (this.options.externalControl) + this.options.externalControl.observe(pair.key, listener); + }.bind(this)); + }, + removeForm: function() { + if (!this._form) return; + this._form.remove(); + this._form = null; + this._controls = { }; + }, + showSaving: function() { + this._oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + this.element.addClassName(this.options.savingClassName); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + }, + triggerCallback: function(cbName, arg) { + if ('function' == typeof this.options[cbName]) { + this.options[cbName](this, arg); + } + }, + unregisterListeners: function() { + $H(this._listeners).each(function(pair) { + if (!this.options.externalControlOnly) + this.element.stopObserving(pair.key, pair.value); + if (this.options.externalControl) + this.options.externalControl.stopObserving(pair.key, pair.value); + }.bind(this)); + }, + wrapUp: function(transport) { + this.leaveEditMode(); + // Can't use triggerCallback due to backward compatibility: requires + // binding + direct element + this._boundComplete(transport, this.element); + } +}); + +Object.extend(Ajax.InPlaceEditor.prototype, { + dispose: Ajax.InPlaceEditor.prototype.destroy +}); + +Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { + initialize: function($super, element, url, options) { + this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; + $super(element, url, options); + }, + + createEditField: function() { + var list = document.createElement('select'); + list.name = this.options.paramName; + list.size = 1; + this._controls.editor = list; + this._collection = this.options.collection || []; + if (this.options.loadCollectionURL) + this.loadCollection(); + else + this.checkForExternalText(); + this._form.appendChild(this._controls.editor); + }, + + loadCollection: function() { + this._form.addClassName(this.options.loadingClassName); + this.showLoadingText(this.options.loadingCollectionText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + var js = transport.responseText.strip(); + if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check + throw 'Server returned an invalid collection representation.'; + this._collection = eval(js); + this.checkForExternalText(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadCollectionURL, options); + }, + + showLoadingText: function(text) { + this._controls.editor.disabled = true; + var tempOption = this._controls.editor.firstChild; + if (!tempOption) { + tempOption = document.createElement('option'); + tempOption.value = ''; + this._controls.editor.appendChild(tempOption); + tempOption.selected = true; + } + tempOption.update((text || '').stripScripts().stripTags()); + }, + + checkForExternalText: function() { + this._text = this.getText(); + if (this.options.loadTextURL) + this.loadExternalText(); + else + this.buildOptionList(); + }, + + loadExternalText: function() { + this.showLoadingText(this.options.loadingText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._text = transport.responseText.strip(); + this.buildOptionList(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + + buildOptionList: function() { + this._form.removeClassName(this.options.loadingClassName); + this._collection = this._collection.map(function(entry) { + return 2 === entry.length ? entry : [entry, entry].flatten(); + }); + var marker = ('value' in this.options) ? this.options.value : this._text; + var textFound = this._collection.any(function(entry) { + return entry[0] == marker; + }.bind(this)); + this._controls.editor.update(''); + var option; + this._collection.each(function(entry, index) { + option = document.createElement('option'); + option.value = entry[0]; + option.selected = textFound ? entry[0] == marker : 0 == index; + option.appendChild(document.createTextNode(entry[1])); + this._controls.editor.appendChild(option); + }.bind(this)); + this._controls.editor.disabled = false; + Field.scrollFreeActivate(this._controls.editor); + } +}); + +//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** +//**** This only exists for a while, in order to let **** +//**** users adapt to the new API. Read up on the new **** +//**** API and convert your code to it ASAP! **** + +Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { + if (!options) return; + function fallback(name, expr) { + if (name in options || expr === undefined) return; + options[name] = expr; + }; + fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : + options.cancelLink == options.cancelButton == false ? false : undefined))); + fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : + options.okLink == options.okButton == false ? false : undefined))); + fallback('highlightColor', options.highlightcolor); + fallback('highlightEndColor', options.highlightendcolor); +}; + +Object.extend(Ajax.InPlaceEditor, { + DefaultOptions: { + ajaxOptions: { }, + autoRows: 3, // Use when multi-line w/ rows == 1 + cancelControl: 'link', // 'link'|'button'|false + cancelText: 'cancel', + clickToEditText: 'Click to edit', + externalControl: null, // id|elt + externalControlOnly: false, + fieldPostCreation: 'activate', // 'activate'|'focus'|false + formClassName: 'inplaceeditor-form', + formId: null, // id|elt + highlightColor: '#ffff99', + highlightEndColor: '#ffffff', + hoverClassName: '', + htmlResponse: true, + loadingClassName: 'inplaceeditor-loading', + loadingText: 'Loading...', + okControl: 'button', // 'link'|'button'|false + okText: 'ok', + paramName: 'value', + rows: 1, // If 1 and multi-line, uses autoRows + savingClassName: 'inplaceeditor-saving', + savingText: 'Saving...', + size: 0, + stripLoadedTextTags: false, + submitOnBlur: false, + textAfterControls: '', + textBeforeControls: '', + textBetweenControls: '' + }, + DefaultCallbacks: { + callback: function(form) { + return Form.serialize(form); + }, + onComplete: function(transport, element) { + // For backward compatibility, this one is bound to the IPE, and passes + // the element directly. It was too often customized, so we don't break it. + new Effect.Highlight(element, { + startcolor: this.options.highlightColor, keepBackgroundImage: true }); + }, + onEnterEditMode: null, + onEnterHover: function(ipe) { + ipe.element.style.backgroundColor = ipe.options.highlightColor; + if (ipe._effect) + ipe._effect.cancel(); + }, + onFailure: function(transport, ipe) { + alert('Error communication with the server: ' + transport.responseText.stripTags()); + }, + onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. + onLeaveEditMode: null, + onLeaveHover: function(ipe) { + ipe._effect = new Effect.Highlight(ipe.element, { + startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, + restorecolor: ipe._originalBackground, keepBackgroundImage: true + }); + } + }, + Listeners: { + click: 'enterEditMode', + keydown: 'checkForEscapeOrReturn', + mouseover: 'enterHover', + mouseout: 'leaveHover' + } +}); + +Ajax.InPlaceCollectionEditor.DefaultOptions = { + loadingCollectionText: 'Loading options...' +}; + +// Delayed observer, like Form.Element.Observer, +// but waits for delay after last key input +// Ideal for live-search fields + +Form.Element.DelayedObserver = Class.create({ + initialize: function(element, delay, callback) { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function(event) { + if(this.lastValue == $F(this.element)) return; + if(this.timer) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() { + this.timer = null; + this.callback(this.element, $F(this.element)); + } +}); diff --git a/doc/1.6.1/javascripts/effects.js b/doc/1.6.1/javascripts/effects.js new file mode 100644 index 000000000..718a88d21 --- /dev/null +++ b/doc/1.6.1/javascripts/effects.js @@ -0,0 +1,1120 @@ +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if (this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if (this.slice(0,1) == '#') { + if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if (this.length==7) color = this.toLowerCase(); + } + } + return (color.length==7 ? color : (arguments[0] || this)); +}; + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +}; + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +}; + +Element.setContentZoom = function(element, percent) { + element = $(element); + element.setStyle({fontSize: (percent/100) + 'em'}); + if (Prototype.Browser.WebKit) window.scrollBy(0,0); + return element; +}; + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +}; + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + Transitions: { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + 0.5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + return pos > 1 ? 1 : pos; + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; + }, + pulse: function(pos, pulses) { + pulses = pulses || 5; + return ( + ((pos % (1/pulses)) * pulses).round() == 0 ? + ((pos * pulses * 2) - (pos * pulses * 2).floor()) : + 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) + ); + }, + spring: function(pos) { + return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } + }, + DefaultOptions: { + duration: 1.0, // seconds + fps: 100, // 100= assume 66fps max. + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' + }, + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; + + element = $(element); + $A(element.childNodes).each( function(child) { + if (child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + new Element('span', {style: tagifyStyle}).update( + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if (((typeof element == 'object') || + Object.isFunction(element)) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || { }); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || { }); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(Enumerable, { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = Object.isString(effect.options.queue) ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if (!this.interval) + this.interval = setInterval(this.loop.bind(this), 15); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if (this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + for(var i=0, len=this.effects.length;i= this.startOn) { + if (timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if (this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / this.totalTime, + frame = (pos * this.totalFrames).round(); + if (frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + cancel: function() { + if (!this.options.sync) + Effect.Queues.get(Object.isString(this.options.queue) ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if (this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + var data = $H(); + for(property in this) + if (!Object.isFunction(this[property])) data.set(property, this[property]); + return '#'; + } +}); + +Effect.Parallel = Class.create(Effect.Base, { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if (effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Tween = Class.create(Effect.Base, { + initialize: function(object, from, to) { + object = Object.isString(object) ? $(object) : object; + var args = $A(arguments), method = args.last(), + options = args.length == 5 ? args[3] : null; + this.method = Object.isFunction(method) ? method.bind(object) : + Object.isFunction(object[method]) ? object[method].bind(object) : + function(value) { object[method] = value }; + this.start(Object.extend({ from: from, to: to }, options || { })); + }, + update: function(position) { + this.method(position); + } +}); + +Effect.Event = Class.create(Effect.Base, { + initialize: function() { + this.start(Object.extend({ duration: 0 }, arguments[0] || { })); + }, + update: Prototype.emptyFunction +}); + +Effect.Opacity = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || { }); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if (this.options.mode == 'absolute') { + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: (this.options.x * position + this.originalLeft).round() + 'px', + top: (this.options.y * position + this.originalTop).round() + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); +}; + +Effect.Scale = Class.create(Effect.Base, { + initialize: function(element, percent) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or { } with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || { }); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = { }; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if (fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if (this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if (/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if (!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if (this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = { }; + if (this.options.scaleX) d.width = width.round() + 'px'; + if (this.options.scaleY) d.height = height.round() + 'px'; + if (this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if (this.elementPositioning == 'absolute') { + if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if (this.options.scaleY) d.top = -topd + 'px'; + if (this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if (this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { }; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } + if (!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if (!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = function(element) { + var options = arguments[1] || { }, + scrollOffsets = document.viewport.getScrollOffsets(), + elementOffsets = $(element).cumulativeOffset(), + max = document.viewport.getScrollOffsets[0] - document.viewport.getHeight(); + + if (options.offset) elementOffsets[1] += options.offset; + + return new Effect.Tween(null, + scrollOffsets.top, + elementOffsets[1] > max ? max : elementOffsets[1], + options, + function(p){ scrollTo(scrollOffsets.left, p.round()) } + ); +}; + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if (effect.options.to!=0) return; + effect.element.hide().setStyle({opacity: oldOpacity}); + } + }, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from).show(); + }}, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element) + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().setStyle(oldStyle); } + }, arguments[1] || { }) + ); +}; + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }, arguments[1] || { }) + ); +}; + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || { })); +}; + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); + } + }) + } + }, arguments[1] || { })); +}; + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); + } + }, arguments[1] || { })); +}; + +Effect.Shake = function(element) { + element = $(element); + var options = Object.extend({ + distance: 20, + duration: 0.5 + }, arguments[1] || {}); + var distance = parseFloat(options.distance); + var split = parseFloat(options.duration) / 10.0; + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { + effect.element.undoPositioned().setStyle(oldStyle); + }}) }}) }}) }}) }}) }}); +}; + +Effect.SlideDown = function(element) { + element = $(element).cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || { }) + ); +}; + +Effect.SlideUp = function(element) { + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); + } + }, arguments[1] || { }) + ); +}; + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }); +}; + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide().makeClipping().makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); + } + }, options) + ) + } + }); +}; + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } + }, options) + ); +}; + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || { }; + var oldOpacity = element.getInlineOpacity(); + var transition = options.transition || Effect.Transitions.sinoidal; + var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; + reverser.bind(transition); + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 2.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +}; + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + element.makeClipping(); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().setStyle(oldStyle); + } }); + }}, arguments[1] || { })); +}; + +Effect.Morph = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: { } + }, arguments[1] || { }); + + if (!Object.isString(options.style)) this.style = $H(options.style); + else { + if (options.style.include(':')) + this.style = options.style.parseStyle(); + else { + this.element.addClassName(options.style); + this.style = $H(this.element.getStyles()); + this.element.removeClassName(options.style); + var css = this.element.getStyles(); + this.style = this.style.reject(function(style) { + return style.value == css[style.key]; + }); + options.afterFinishInternal = function(effect) { + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + effect.element.style[transform.style] = ''; + }); + } + } + } + this.start(options); + }, + + setup: function(){ + function parseColor(color){ + if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ) + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0], value = pair[1], unit = null; + + if (value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if (property == 'opacity') { + value = parseFloat(value); + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if (Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } + + var originalValue = this.element.getStyle(property); + return { + style: property.camelize(), + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }; + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ) + }); + }, + update: function(position) { + var style = { }, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : + (transform.originalValue + + (transform.targetValue - transform.originalValue) * position).toFixed(3) + + (transform.unit === null ? '' : transform.unit); + this.element.setStyle(style, true); + } +}); + +Effect.Transform = Class.create({ + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || { }; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + track = $H(track); + var data = track.values().first(); + this.tracks.push($H({ + ids: track.keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); + var elements = [$(ids) || $$(ids)].flatten(); + return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.__parseStyleElement = document.createElement('div'); +String.prototype.parseStyle = function(){ + var style, styleRules = $H(); + if (Prototype.Browser.WebKit) + style = new Element('div',{style:this}).style; + else { + String.__parseStyleElement.innerHTML = '
    '; + style = String.__parseStyleElement.childNodes[0].style; + } + + Element.CSS_PROPERTIES.each(function(property){ + if (style[property]) styleRules.set(property, style[property]); + }); + + if (Prototype.Browser.IE && this.include('opacity')) + styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); + + return styleRules; +}; + +if (document.defaultView && document.defaultView.getComputedStyle) { + Element.getStyles = function(element) { + var css = document.defaultView.getComputedStyle($(element), null); + return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { + styles[property] = css[property]; + return styles; + }); + }; +} else { + Element.getStyles = function(element) { + element = $(element); + var css = element.currentStyle, styles; + styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { + results[property] = css[property]; + return results; + }); + if (!styles.opacity) styles.opacity = element.getOpacity(); + return styles; + }; +}; + +Effect.Methods = { + morph: function(element, style) { + element = $(element); + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); + return element; + }, + visualEffect: function(element, effect, options) { + element = $(element) + var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[klass](element, options); + return element; + }, + highlight: function(element, options) { + element = $(element); + new Effect.Highlight(element, options); + return element; + } +}; + +$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ + 'pulsate shake puff squish switchOff dropOut').each( + function(effect) { + Effect.Methods[effect] = function(element, options){ + element = $(element); + Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); + return element; + } + } +); + +$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( + function(f) { Effect.Methods[f] = Element[f]; } +); + +Element.addMethods(Effect.Methods); diff --git a/doc/1.6.1/javascripts/item_index.js b/doc/1.6.1/javascripts/item_index.js new file mode 100644 index 000000000..bd6da2616 --- /dev/null +++ b/doc/1.6.1/javascripts/item_index.js @@ -0,0 +1,413 @@ +if (!window.PDoc) window.PDoc = {}; +PDoc.elements = { + 'Element#remove': { 'name': 'Element#remove', 'type': 'instance method', 'path': 'dom/element/prototype/remove' }, +'Form.Element.serialize': { 'name': 'Form.Element.serialize', 'type': 'class method', 'path': 'dom/form/element/serialize' }, +'Enumerable#zip': { 'name': 'Enumerable#zip', 'type': 'instance method', 'path': 'language/enumerable/prototype/zip' }, +'String': { 'name': 'String', 'type': 'class', 'path': 'language/string' }, +'Element.descendantOf': { 'name': 'Element.descendantOf', 'type': 'class method', 'path': 'dom/element/descendantof' }, +'Element#immediateDescendants': { 'name': 'Element#immediateDescendants', 'type': 'instance method', 'path': 'dom/element/prototype/immediatedescendants' }, +'Element#makePositioned': { 'name': 'Element#makePositioned', 'type': 'instance method', 'path': 'dom/element/prototype/makepositioned' }, +'Element.stopObserving': { 'name': 'Element.stopObserving', 'type': 'class method', 'path': 'dom/element/stopobserving' }, +'new Ajax.PeriodicalUpdater': { 'name': 'new Ajax.PeriodicalUpdater', 'type': 'constructor', 'path': 'ajax/ajax/periodicalupdater/new' }, +'String#extractScripts': { 'name': 'String#extractScripts', 'type': 'instance method', 'path': 'language/string/prototype/extractscripts' }, +'Event': { 'name': 'Event', 'type': 'class', 'path': 'dom/event' }, +'String#blank': { 'name': 'String#blank', 'type': 'instance method', 'path': 'language/string/prototype/blank' }, +'Element#positionedOffset': { 'name': 'Element#positionedOffset', 'type': 'instance method', 'path': 'dom/element/prototype/positionedoffset' }, +'Number#round': { 'name': 'Number#round', 'type': 'instance method', 'path': 'language/number/prototype/round' }, +'Array#uniq': { 'name': 'Array#uniq', 'type': 'instance method', 'path': 'language/array/prototype/uniq' }, +'Template#evaluate': { 'name': 'Template#evaluate', 'type': 'instance method', 'path': 'language/template/prototype/evaluate' }, +'Form.Element#getValue': { 'name': 'Form.Element#getValue', 'type': 'instance method', 'path': 'dom/form/element/prototype/getvalue' }, +'Event.pointerX': { 'name': 'Event.pointerX', 'type': 'class method', 'path': 'dom/event/pointerx' }, +'Element.getHeight': { 'name': 'Element.getHeight', 'type': 'class method', 'path': 'dom/element/getheight' }, +'Form.request': { 'name': 'Form.request', 'type': 'class method', 'path': 'dom/form/request' }, +'Array': { 'name': 'Array', 'type': 'class', 'path': 'language/array' }, +'Try': { 'name': 'Try', 'type': 'namespace', 'path': 'language/try' }, +'Event.pointerY': { 'name': 'Event.pointerY', 'type': 'class method', 'path': 'dom/event/pointery' }, +'Element.select': { 'name': 'Element.select', 'type': 'class method', 'path': 'dom/element/select' }, +'$A': { 'name': '$A', 'type': 'utility', 'path': 'language/dollara' }, +'Number#floor': { 'name': 'Number#floor', 'type': 'instance method', 'path': 'language/number/prototype/floor' }, +'Element#getOffsetParent': { 'name': 'Element#getOffsetParent', 'type': 'instance method', 'path': 'dom/element/prototype/getoffsetparent' }, +'ObjectRange': { 'name': 'ObjectRange', 'type': 'class', 'path': 'language/objectrange' }, +'new Element': { 'name': 'new Element', 'type': 'constructor', 'path': 'dom/element/new' }, +'Element.hasClassName': { 'name': 'Element.hasClassName', 'type': 'class method', 'path': 'dom/element/hasclassname' }, +'String#empty': { 'name': 'String#empty', 'type': 'instance method', 'path': 'language/string/prototype/empty' }, +'Event.pointer': { 'name': 'Event.pointer', 'type': 'class method', 'path': 'dom/event/pointer' }, +'Element#setOpacity': { 'name': 'Element#setOpacity', 'type': 'instance method', 'path': 'dom/element/prototype/setopacity' }, +'Object.isHash': { 'name': 'Object.isHash', 'type': 'class method', 'path': 'language/object/ishash' }, +'Ajax.Response#request': { 'name': 'Ajax.Response#request', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/request' }, +'Selector.split': { 'name': 'Selector.split', 'type': 'class method', 'path': 'dom/selector/split' }, +'Element.viewportOffset': { 'name': 'Element.viewportOffset', 'type': 'class method', 'path': 'dom/element/viewportoffset' }, +'String.interpret': { 'name': 'String.interpret', 'type': 'class method', 'path': 'language/string/interpret' }, +'Event#element': { 'name': 'Event#element', 'type': 'instance method', 'path': 'dom/event/prototype/element' }, +'String#scan': { 'name': 'String#scan', 'type': 'instance method', 'path': 'language/string/prototype/scan' }, +'document.fire': { 'name': 'document.fire', 'type': 'class method', 'path': 'dom/document/fire' }, +'Object.toQueryString': { 'name': 'Object.toQueryString', 'type': 'class method', 'path': 'language/object/toquerystring' }, +'Element#hide': { 'name': 'Element#hide', 'type': 'instance method', 'path': 'dom/element/prototype/hide' }, +'$F': { 'name': '$F', 'type': 'utility', 'path': 'dom/dollarf' }, +'Hash#toQueryString': { 'name': 'Hash#toQueryString', 'type': 'instance method', 'path': 'language/hash/prototype/toquerystring' }, +'Ajax.Responders.register': { 'name': 'Ajax.Responders.register', 'type': 'class method', 'path': 'ajax/ajax/responders/register' }, +'Hash#merge': { 'name': 'Hash#merge', 'type': 'instance method', 'path': 'language/hash/prototype/merge' }, +'Enumerable#grep': { 'name': 'Enumerable#grep', 'type': 'instance method', 'path': 'language/enumerable/prototype/grep' }, +'Object.toHTML': { 'name': 'Object.toHTML', 'type': 'class method', 'path': 'language/object/tohtml' }, +'Element.recursivelyCollect': { 'name': 'Element.recursivelyCollect', 'type': 'class method', 'path': 'dom/element/recursivelycollect' }, +'Element.adjacent': { 'name': 'Element.adjacent', 'type': 'class method', 'path': 'dom/element/adjacent' }, +'RegExp#match': { 'name': 'RegExp#match', 'type': 'instance method', 'path': 'language/regexp/prototype/match' }, +'Element.next': { 'name': 'Element.next', 'type': 'class method', 'path': 'dom/element/next' }, +'$H': { 'name': '$H', 'type': 'utility', 'path': 'language/dollarh' }, +'Element#getHeight': { 'name': 'Element#getHeight', 'type': 'instance method', 'path': 'dom/element/prototype/getheight' }, +'Element#recursivelyCollect': { 'name': 'Element#recursivelyCollect', 'type': 'instance method', 'path': 'dom/element/prototype/recursivelycollect' }, +'Element.getStorage': { 'name': 'Element.getStorage', 'type': 'class method', 'path': 'dom/element/getstorage' }, +'String#toQueryParams': { 'name': 'String#toQueryParams', 'type': 'instance method', 'path': 'language/string/prototype/toqueryparams' }, +'Element.insert': { 'name': 'Element.insert', 'type': 'class method', 'path': 'dom/element/insert' }, +'Enumerable#invoke': { 'name': 'Enumerable#invoke', 'type': 'instance method', 'path': 'language/enumerable/prototype/invoke' }, +'Element.addMethods': { 'name': 'Element.addMethods', 'type': 'class method', 'path': 'dom/element/addmethods' }, +'Element#setStyle': { 'name': 'Element#setStyle', 'type': 'instance method', 'path': 'dom/element/prototype/setstyle' }, +'Array#last': { 'name': 'Array#last', 'type': 'instance method', 'path': 'language/array/prototype/last' }, +'Element#show': { 'name': 'Element#show', 'type': 'instance method', 'path': 'dom/element/prototype/show' }, +'Function#bind': { 'name': 'Function#bind', 'type': 'instance method', 'path': 'language/function/prototype/bind' }, +'Element.observe': { 'name': 'Element.observe', 'type': 'class method', 'path': 'dom/element/observe' }, +'document.viewport.getScrollOffsets': { 'name': 'document.viewport.getScrollOffsets', 'type': 'class method', 'path': 'dom/document/viewport/getscrolloffsets' }, +'String#unfilterJSON': { 'name': 'String#unfilterJSON', 'type': 'instance method', 'path': 'language/string/prototype/unfilterjson' }, +'Hash#index': { 'name': 'Hash#index', 'type': 'instance method', 'path': 'language/hash/prototype/index' }, +'Array#clear': { 'name': 'Array#clear', 'type': 'instance method', 'path': 'language/array/prototype/clear' }, +'Form.Element.getValue': { 'name': 'Form.Element.getValue', 'type': 'class method', 'path': 'dom/form/element/getvalue' }, +'Element.absolutize': { 'name': 'Element.absolutize', 'type': 'class method', 'path': 'dom/element/absolutize' }, +'Array.from': { 'name': 'Array.from', 'type': 'class method', 'path': 'language/array/from' }, +'Element.update': { 'name': 'Element.update', 'type': 'class method', 'path': 'dom/element/update' }, +'Ajax.Response#responseXML': { 'name': 'Ajax.Response#responseXML', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsexml' }, +'Form.Element#serialize': { 'name': 'Form.Element#serialize', 'type': 'instance method', 'path': 'dom/form/element/prototype/serialize' }, +'$R': { 'name': '$R', 'type': 'utility', 'path': 'language/dollarr' }, +'Form.Element.present': { 'name': 'Form.Element.present', 'type': 'class method', 'path': 'dom/form/element/present' }, +'Array#toJSON': { 'name': 'Array#toJSON', 'type': 'instance method', 'path': 'language/array/prototype/tojson' }, +'Element.clone': { 'name': 'Element.clone', 'type': 'class method', 'path': 'dom/element/clone' }, +'Element#writeAttribute': { 'name': 'Element#writeAttribute', 'type': 'instance method', 'path': 'dom/element/prototype/writeattribute' }, +'Enumerable#inject': { 'name': 'Enumerable#inject', 'type': 'instance method', 'path': 'language/enumerable/prototype/inject' }, +'Element.visible': { 'name': 'Element.visible', 'type': 'class method', 'path': 'dom/element/visible' }, +'Element#next': { 'name': 'Element#next', 'type': 'instance method', 'path': 'dom/element/prototype/next' }, +'Element#previous': { 'name': 'Element#previous', 'type': 'instance method', 'path': 'dom/element/prototype/previous' }, +'Element': { 'name': 'Element', 'type': 'class', 'path': 'dom/element' }, +'new Selector': { 'name': 'new Selector', 'type': 'constructor', 'path': 'dom/selector/new' }, +'Element#descendants': { 'name': 'Element#descendants', 'type': 'instance method', 'path': 'dom/element/prototype/descendants' }, +'Object': { 'name': 'Object', 'type': 'class', 'path': 'language/object' }, +'Enumerable#include': { 'name': 'Enumerable#include', 'type': 'instance method', 'path': 'language/enumerable/prototype/include' }, +'Element#replace': { 'name': 'Element#replace', 'type': 'instance method', 'path': 'dom/element/prototype/replace' }, +'String#dasherize': { 'name': 'String#dasherize', 'type': 'instance method', 'path': 'language/string/prototype/dasherize' }, +'Element#toggle': { 'name': 'Element#toggle', 'type': 'instance method', 'path': 'dom/element/prototype/toggle' }, +'String#interpolate': { 'name': 'String#interpolate', 'type': 'instance method', 'path': 'language/string/prototype/interpolate' }, +'new ObjectRange': { 'name': 'new ObjectRange', 'type': 'constructor', 'path': 'language/objectrange/new' }, +'String#camelize': { 'name': 'String#camelize', 'type': 'instance method', 'path': 'language/string/prototype/camelize' }, +'Object.isElement': { 'name': 'Object.isElement', 'type': 'class method', 'path': 'language/object/iselement' }, +'Element#relativize': { 'name': 'Element#relativize', 'type': 'instance method', 'path': 'dom/element/prototype/relativize' }, +'Array#flatten': { 'name': 'Array#flatten', 'type': 'instance method', 'path': 'language/array/prototype/flatten' }, +'String#unescapeHTML': { 'name': 'String#unescapeHTML', 'type': 'instance method', 'path': 'language/string/prototype/unescapehtml' }, +'Element.makePositioned': { 'name': 'Element.makePositioned', 'type': 'class method', 'path': 'dom/element/makepositioned' }, +'Event#isMiddleClick': { 'name': 'Event#isMiddleClick', 'type': 'instance method', 'path': 'dom/event/prototype/ismiddleclick' }, +'document': { 'name': 'document', 'type': 'namespace', 'path': 'dom/document' }, +'Abstract.EventObserver': { 'name': 'Abstract.EventObserver', 'type': 'class', 'path': 'dom/abstract/eventobserver' }, +'String#times': { 'name': 'String#times', 'type': 'instance method', 'path': 'language/string/prototype/times' }, +'Event.findElement': { 'name': 'Event.findElement', 'type': 'class method', 'path': 'dom/event/findelement' }, +'Element.positionedOffset': { 'name': 'Element.positionedOffset', 'type': 'class method', 'path': 'dom/element/positionedoffset' }, +'$': { 'name': '$', 'type': 'utility', 'path': 'dom/dollar' }, +'Abstract.TimedObserver': { 'name': 'Abstract.TimedObserver', 'type': 'class', 'path': 'dom/abstract/timedobserver' }, +'Hash#get': { 'name': 'Hash#get', 'type': 'instance method', 'path': 'language/hash/prototype/get' }, +'Number': { 'name': 'Number', 'type': 'class', 'path': 'language/number' }, +'Element.firstDescendant': { 'name': 'Element.firstDescendant', 'type': 'class method', 'path': 'dom/element/firstdescendant' }, +'document.viewport.getDimensions': { 'name': 'document.viewport.getDimensions', 'type': 'class method', 'path': 'dom/document/viewport/getdimensions' }, +'Ajax.Response#statusText': { 'name': 'Ajax.Response#statusText', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/statustext' }, +'Element.remove': { 'name': 'Element.remove', 'type': 'class method', 'path': 'dom/element/remove' }, +'Element.setStyle': { 'name': 'Element.setStyle', 'type': 'class method', 'path': 'dom/element/setstyle' }, +'new Form.Observer': { 'name': 'new Form.Observer', 'type': 'constructor', 'path': 'dom/form/observer/new' }, +'Element.up': { 'name': 'Element.up', 'type': 'class method', 'path': 'dom/element/up' }, +'Element.hide': { 'name': 'Element.hide', 'type': 'class method', 'path': 'dom/element/hide' }, +'Function': { 'name': 'Function', 'type': 'class', 'path': 'language/function' }, +'Event.isMiddleClick': { 'name': 'Event.isMiddleClick', 'type': 'class method', 'path': 'dom/event/ismiddleclick' }, +'Number#ceil': { 'name': 'Number#ceil', 'type': 'instance method', 'path': 'language/number/prototype/ceil' }, +'Form.Element#setValue': { 'name': 'Form.Element#setValue', 'type': 'instance method', 'path': 'dom/form/element/prototype/setvalue' }, +'Element.getStyle': { 'name': 'Element.getStyle', 'type': 'class method', 'path': 'dom/element/getstyle' }, +'Element#down': { 'name': 'Element#down', 'type': 'instance method', 'path': 'dom/element/prototype/down' }, +'Element.show': { 'name': 'Element.show', 'type': 'class method', 'path': 'dom/element/show' }, +'Element#cumulativeScrollOffset': { 'name': 'Element#cumulativeScrollOffset', 'type': 'instance method', 'path': 'dom/element/prototype/cumulativescrolloffset' }, +'Form.getElements': { 'name': 'Form.getElements', 'type': 'class method', 'path': 'dom/form/getelements' }, +'Element.writeAttribute': { 'name': 'Element.writeAttribute', 'type': 'class method', 'path': 'dom/element/writeattribute' }, +'Element.cleanWhitespace': { 'name': 'Element.cleanWhitespace', 'type': 'class method', 'path': 'dom/element/cleanwhitespace' }, +'Form#request': { 'name': 'Form#request', 'type': 'instance method', 'path': 'dom/form/prototype/request' }, +'Date': { 'name': 'Date', 'type': 'class', 'path': 'language/date' }, +'Array#clone': { 'name': 'Array#clone', 'type': 'instance method', 'path': 'language/array/prototype/clone' }, +'Element.inspect': { 'name': 'Element.inspect', 'type': 'class method', 'path': 'dom/element/inspect' }, +'Event#isLeftClick': { 'name': 'Event#isLeftClick', 'type': 'instance method', 'path': 'dom/event/prototype/isleftclick' }, +'Element.previous': { 'name': 'Element.previous', 'type': 'class method', 'path': 'dom/element/previous' }, +'Element#descendantOf': { 'name': 'Element#descendantOf', 'type': 'instance method', 'path': 'dom/element/prototype/descendantof' }, +'Selector#findElements': { 'name': 'Selector#findElements', 'type': 'instance method', 'path': 'dom/selector/prototype/findelements' }, +'Element#getWidth': { 'name': 'Element#getWidth', 'type': 'instance method', 'path': 'dom/element/prototype/getwidth' }, +'new PeriodicalExecuter': { 'name': 'new PeriodicalExecuter', 'type': 'constructor', 'path': 'language/periodicalexecuter/new' }, +'Template': { 'name': 'Template', 'type': 'class', 'path': 'language/template' }, +'String#capitalize': { 'name': 'String#capitalize', 'type': 'instance method', 'path': 'language/string/prototype/capitalize' }, +'Element#getElementsBySelector': { 'name': 'Element#getElementsBySelector', 'type': 'instance method', 'path': 'dom/element/prototype/getelementsbyselector' }, +'Enumerable#select': { 'name': 'Enumerable#select', 'type': 'instance method', 'path': 'language/enumerable/prototype/select' }, +'Event#pointer': { 'name': 'Event#pointer', 'type': 'instance method', 'path': 'dom/event/prototype/pointer' }, +'Ajax.Response.getAllResponseHeaders': { 'name': 'Ajax.Response.getAllResponseHeaders', 'type': 'class method', 'path': 'ajax/ajax/response/getallresponseheaders' }, +'Hash#clone': { 'name': 'Hash#clone', 'type': 'instance method', 'path': 'language/hash/prototype/clone' }, +'RegExp.escape': { 'name': 'RegExp.escape', 'type': 'class method', 'path': 'language/regexp/escape' }, +'Element#cumulativeOffset': { 'name': 'Element#cumulativeOffset', 'type': 'instance method', 'path': 'dom/element/prototype/cumulativeoffset' }, +'Element#getOpacity': { 'name': 'Element#getOpacity', 'type': 'instance method', 'path': 'dom/element/prototype/getopacity' }, +'Hash#inspect': { 'name': 'Hash#inspect', 'type': 'instance method', 'path': 'language/hash/prototype/inspect' }, +'Event.fire': { 'name': 'Event.fire', 'type': 'class method', 'path': 'dom/event/fire' }, +'Element.extend': { 'name': 'Element.extend', 'type': 'class method', 'path': 'dom/element/extend' }, +'Form.Element.focus': { 'name': 'Form.Element.focus', 'type': 'class method', 'path': 'dom/form/element/focus' }, +'Ajax.PeriodicalUpdater#start': { 'name': 'Ajax.PeriodicalUpdater#start', 'type': 'instance method', 'path': 'ajax/ajax/periodicalupdater/prototype/start' }, +'Element.getElementsBySelector': { 'name': 'Element.getElementsBySelector', 'type': 'class method', 'path': 'dom/element/getelementsbyselector' }, +'Element#makeClipping': { 'name': 'Element#makeClipping', 'type': 'instance method', 'path': 'dom/element/prototype/makeclipping' }, +'Element.makeClipping': { 'name': 'Element.makeClipping', 'type': 'class method', 'path': 'dom/element/makeclipping' }, +'Abstract': { 'name': 'Abstract', 'type': 'namespace', 'path': 'dom/abstract' }, +'Element.addClassName': { 'name': 'Element.addClassName', 'type': 'class method', 'path': 'dom/element/addclassname' }, +'Element.removeClassName': { 'name': 'Element.removeClassName', 'type': 'class method', 'path': 'dom/element/removeclassname' }, +'String#toJSON': { 'name': 'String#toJSON', 'type': 'instance method', 'path': 'language/string/prototype/tojson' }, +'Form.Element.clear': { 'name': 'Form.Element.clear', 'type': 'class method', 'path': 'dom/form/element/clear' }, +'Element.setOpacity': { 'name': 'Element.setOpacity', 'type': 'class method', 'path': 'dom/element/setopacity' }, +'String#truncate': { 'name': 'String#truncate', 'type': 'instance method', 'path': 'language/string/prototype/truncate' }, +'Form.disable': { 'name': 'Form.disable', 'type': 'class method', 'path': 'dom/form/disable' }, +'Element#hasClassName': { 'name': 'Element#hasClassName', 'type': 'instance method', 'path': 'dom/element/prototype/hasclassname' }, +'Ajax.Response#getHeader': { 'name': 'Ajax.Response#getHeader', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getheader' }, +'Element#fire': { 'name': 'Element#fire', 'type': 'instance method', 'path': 'dom/element/prototype/fire' }, +'Number#toColorPart': { 'name': 'Number#toColorPart', 'type': 'instance method', 'path': 'language/number/prototype/tocolorpart' }, +'Selector.findChildElements': { 'name': 'Selector.findChildElements', 'type': 'class method', 'path': 'dom/selector/findchildelements' }, +'Element#firstDescendant': { 'name': 'Element#firstDescendant', 'type': 'instance method', 'path': 'dom/element/prototype/firstdescendant' }, +'Form.Element.disable': { 'name': 'Form.Element.disable', 'type': 'class method', 'path': 'dom/form/element/disable' }, +'String#evalJSON': { 'name': 'String#evalJSON', 'type': 'instance method', 'path': 'language/string/prototype/evaljson' }, +'Form.Element.setValue': { 'name': 'Form.Element.setValue', 'type': 'class method', 'path': 'dom/form/element/setvalue' }, +'Ajax.Request#success': { 'name': 'Ajax.Request#success', 'type': 'instance method', 'path': 'ajax/ajax/request/prototype/success' }, +'String#succ': { 'name': 'String#succ', 'type': 'instance method', 'path': 'language/string/prototype/succ' }, +'Ajax.PeriodicalUpdater#stop': { 'name': 'Ajax.PeriodicalUpdater#stop', 'type': 'instance method', 'path': 'ajax/ajax/periodicalupdater/prototype/stop' }, +'Element#select': { 'name': 'Element#select', 'type': 'instance method', 'path': 'dom/element/prototype/select' }, +'PeriodicalExecuter': { 'name': 'PeriodicalExecuter', 'type': 'class', 'path': 'language/periodicalexecuter' }, +'Element#removeClassName': { 'name': 'Element#removeClassName', 'type': 'instance method', 'path': 'dom/element/prototype/removeclassname' }, +'Element#getDimensions': { 'name': 'Element#getDimensions', 'type': 'instance method', 'path': 'dom/element/prototype/getdimensions' }, +'Element#observe': { 'name': 'Element#observe', 'type': 'instance method', 'path': 'dom/element/prototype/observe' }, +'Element#up': { 'name': 'Element#up', 'type': 'instance method', 'path': 'dom/element/prototype/up' }, +'Ajax.Updater': { 'name': 'Ajax.Updater', 'type': 'class', 'path': 'ajax/ajax/updater' }, +'Array#indexOf': { 'name': 'Array#indexOf', 'type': 'instance method', 'path': 'language/array/prototype/indexof' }, +'String#underscore': { 'name': 'String#underscore', 'type': 'instance method', 'path': 'language/string/prototype/underscore' }, +'Event.isRightClick': { 'name': 'Event.isRightClick', 'type': 'class method', 'path': 'dom/event/isrightclick' }, +'Form#findFirstElement': { 'name': 'Form#findFirstElement', 'type': 'instance method', 'path': 'dom/form/prototype/findfirstelement' }, +'String#evalScripts': { 'name': 'String#evalScripts', 'type': 'instance method', 'path': 'language/string/prototype/evalscripts' }, +'Element#clone': { 'name': 'Element#clone', 'type': 'instance method', 'path': 'dom/element/prototype/clone' }, +'$w': { 'name': '$w', 'type': 'utility', 'path': 'language/dollarw' }, +'Class': { 'name': 'Class', 'type': 'namespace', 'path': 'language/class' }, +'Event.stopObserving': { 'name': 'Event.stopObserving', 'type': 'class method', 'path': 'dom/event/stopobserving' }, +'Form.enable': { 'name': 'Form.enable', 'type': 'class method', 'path': 'dom/form/enable' }, +'Array#first': { 'name': 'Array#first', 'type': 'instance method', 'path': 'language/array/prototype/first' }, +'Element.relativize': { 'name': 'Element.relativize', 'type': 'class method', 'path': 'dom/element/relativize' }, +'Enumerable#toArray': { 'name': 'Enumerable#toArray', 'type': 'instance method', 'path': 'language/enumerable/prototype/toarray' }, +'Hash#unset': { 'name': 'Hash#unset', 'type': 'instance method', 'path': 'language/hash/prototype/unset' }, +'Form.getInputs': { 'name': 'Form.getInputs', 'type': 'class method', 'path': 'dom/form/getinputs' }, +'Element#undoPositioned': { 'name': 'Element#undoPositioned', 'type': 'instance method', 'path': 'dom/element/prototype/undopositioned' }, +'Element#cleanWhitespace': { 'name': 'Element#cleanWhitespace', 'type': 'instance method', 'path': 'dom/element/prototype/cleanwhitespace' }, +'Form.Element#present': { 'name': 'Form.Element#present', 'type': 'instance method', 'path': 'dom/form/element/prototype/present' }, +'Form.Element': { 'name': 'Form.Element', 'type': 'namespace', 'path': 'dom/form/element' }, +'Element.ancestors': { 'name': 'Element.ancestors', 'type': 'class method', 'path': 'dom/element/ancestors' }, +'String#startsWith': { 'name': 'String#startsWith', 'type': 'instance method', 'path': 'language/string/prototype/startswith' }, +'Array#compact': { 'name': 'Array#compact', 'type': 'instance method', 'path': 'language/array/prototype/compact' }, +'Element.classNames': { 'name': 'Element.classNames', 'type': 'class method', 'path': 'dom/element/classnames' }, +'String#endsWith': { 'name': 'String#endsWith', 'type': 'instance method', 'path': 'language/string/prototype/endswith' }, +'Element#visible': { 'name': 'Element#visible', 'type': 'instance method', 'path': 'dom/element/prototype/visible' }, +'Class.create': { 'name': 'Class.create', 'type': 'class method', 'path': 'language/class/create' }, +'Element.down': { 'name': 'Element.down', 'type': 'class method', 'path': 'dom/element/down' }, +'Number#abs': { 'name': 'Number#abs', 'type': 'instance method', 'path': 'language/number/prototype/abs' }, +'Enumerable#any': { 'name': 'Enumerable#any', 'type': 'instance method', 'path': 'language/enumerable/prototype/any' }, +'Element.toggle': { 'name': 'Element.toggle', 'type': 'class method', 'path': 'dom/element/toggle' }, +'String#include': { 'name': 'String#include', 'type': 'instance method', 'path': 'language/string/prototype/include' }, +'Enumerable#pluck': { 'name': 'Enumerable#pluck', 'type': 'instance method', 'path': 'language/enumerable/prototype/pluck' }, +'Form.Element.EventObserver': { 'name': 'Form.Element.EventObserver', 'type': 'class', 'path': 'dom/form/element/eventobserver' }, +'Element.getDimensions': { 'name': 'Element.getDimensions', 'type': 'class method', 'path': 'dom/element/getdimensions' }, +'Enumerable#collect': { 'name': 'Enumerable#collect', 'type': 'instance method', 'path': 'language/enumerable/prototype/collect' }, +'Form.Element.Observer': { 'name': 'Form.Element.Observer', 'type': 'class', 'path': 'dom/form/element/observer' }, +'Element#wrap': { 'name': 'Element#wrap', 'type': 'instance method', 'path': 'dom/element/prototype/wrap' }, +'String#gsub': { 'name': 'String#gsub', 'type': 'instance method', 'path': 'language/string/prototype/gsub' }, +'RegExp': { 'name': 'RegExp', 'type': 'class', 'path': 'language/regexp' }, +'Ajax.Request': { 'name': 'Ajax.Request', 'type': 'class', 'path': 'ajax/ajax/request' }, +'Enumerable#inspect': { 'name': 'Enumerable#inspect', 'type': 'instance method', 'path': 'language/enumerable/prototype/inspect' }, +'Form.Element#enable': { 'name': 'Form.Element#enable', 'type': 'instance method', 'path': 'dom/form/element/prototype/enable' }, +'Object.isNumber': { 'name': 'Object.isNumber', 'type': 'class method', 'path': 'language/object/isnumber' }, +'document.stopObserving': { 'name': 'document.stopObserving', 'type': 'class method', 'path': 'dom/document/stopobserving' }, +'String#strip': { 'name': 'String#strip', 'type': 'instance method', 'path': 'language/string/prototype/strip' }, +'Element.toggleClassName': { 'name': 'Element.toggleClassName', 'type': 'class method', 'path': 'dom/element/toggleclassname' }, +'Event#findElement': { 'name': 'Event#findElement', 'type': 'instance method', 'path': 'dom/event/prototype/findelement' }, +'Element.match': { 'name': 'Element.match', 'type': 'class method', 'path': 'dom/element/match' }, +'Event#stop': { 'name': 'Event#stop', 'type': 'instance method', 'path': 'dom/event/prototype/stop' }, +'Form.serialize': { 'name': 'Form.serialize', 'type': 'class method', 'path': 'dom/form/serialize' }, +'Object.clone': { 'name': 'Object.clone', 'type': 'class method', 'path': 'language/object/clone' }, +'Object.isString': { 'name': 'Object.isString', 'type': 'class method', 'path': 'language/object/isstring' }, +'Enumerable#entries': { 'name': 'Enumerable#entries', 'type': 'instance method', 'path': 'language/enumerable/prototype/entries' }, +'Element#siblings': { 'name': 'Element#siblings', 'type': 'instance method', 'path': 'dom/element/prototype/siblings' }, +'Enumerable#member': { 'name': 'Enumerable#member', 'type': 'instance method', 'path': 'language/enumerable/prototype/member' }, +'Element.readAttribute': { 'name': 'Element.readAttribute', 'type': 'class method', 'path': 'dom/element/readattribute' }, +'Ajax.Responders.unregister': { 'name': 'Ajax.Responders.unregister', 'type': 'class method', 'path': 'ajax/ajax/responders/unregister' }, +'Element#addClassName': { 'name': 'Element#addClassName', 'type': 'instance method', 'path': 'dom/element/prototype/addclassname' }, +'Enumerable': { 'name': 'Enumerable', 'type': 'mixin', 'path': 'language/enumerable' }, +'String#stripScripts': { 'name': 'String#stripScripts', 'type': 'instance method', 'path': 'language/string/prototype/stripscripts' }, +'Selector': { 'name': 'Selector', 'type': 'class', 'path': 'dom/selector' }, +'Enumerable#detect': { 'name': 'Enumerable#detect', 'type': 'instance method', 'path': 'language/enumerable/prototype/detect' }, +'Form.findFirstElement': { 'name': 'Form.findFirstElement', 'type': 'class method', 'path': 'dom/form/findfirstelement' }, +'Ajax section': { 'name': 'Ajax section', 'type': 'section', 'path': 'ajax' }, +'Enumerable#every': { 'name': 'Enumerable#every', 'type': 'instance method', 'path': 'language/enumerable/prototype/every' }, +'Enumerable#all': { 'name': 'Enumerable#all', 'type': 'instance method', 'path': 'language/enumerable/prototype/all' }, +'Element.store': { 'name': 'Element.store', 'type': 'class method', 'path': 'dom/element/store' }, +'Language section': { 'name': 'Language section', 'type': 'section', 'path': 'language' }, +'Element.getWidth': { 'name': 'Element.getWidth', 'type': 'class method', 'path': 'dom/element/getwidth' }, +'String#sub': { 'name': 'String#sub', 'type': 'instance method', 'path': 'language/string/prototype/sub' }, +'Enumerable#sortBy': { 'name': 'Enumerable#sortBy', 'type': 'instance method', 'path': 'language/enumerable/prototype/sortby' }, +'Function#delay': { 'name': 'Function#delay', 'type': 'instance method', 'path': 'language/function/prototype/delay' }, +'Element.cumulativeScrollOffset': { 'name': 'Element.cumulativeScrollOffset', 'type': 'class method', 'path': 'dom/element/cumulativescrolloffset' }, +'Element.cumulativeOffset': { 'name': 'Element.cumulativeOffset', 'type': 'class method', 'path': 'dom/element/cumulativeoffset' }, +'Event.observe': { 'name': 'Event.observe', 'type': 'class method', 'path': 'dom/event/observe' }, +'Ajax.Responders': { 'name': 'Ajax.Responders', 'type': 'namespace', 'path': 'ajax/ajax/responders' }, +'Enumerable#find': { 'name': 'Enumerable#find', 'type': 'instance method', 'path': 'language/enumerable/prototype/find' }, +'Array#inspect': { 'name': 'Array#inspect', 'type': 'instance method', 'path': 'language/array/prototype/inspect' }, +'Enumerable#map': { 'name': 'Enumerable#map', 'type': 'instance method', 'path': 'language/enumerable/prototype/map' }, +'Element.fire': { 'name': 'Element.fire', 'type': 'class method', 'path': 'dom/element/fire' }, +'Element.getOpacity': { 'name': 'Element.getOpacity', 'type': 'class method', 'path': 'dom/element/getopacity' }, +'Form#getElements': { 'name': 'Form#getElements', 'type': 'instance method', 'path': 'dom/form/prototype/getelements' }, +'Form#serialize': { 'name': 'Form#serialize', 'type': 'instance method', 'path': 'dom/form/prototype/serialize' }, +'Element.undoPositioned': { 'name': 'Element.undoPositioned', 'type': 'class method', 'path': 'dom/element/undopositioned' }, +'Element#inspect': { 'name': 'Element#inspect', 'type': 'instance method', 'path': 'dom/element/prototype/inspect' }, +'Element#retrieve': { 'name': 'Element#retrieve', 'type': 'instance method', 'path': 'dom/element/prototype/retrieve' }, +'Element.empty': { 'name': 'Element.empty', 'type': 'class method', 'path': 'dom/element/empty' }, +'Element.nextSiblings': { 'name': 'Element.nextSiblings', 'type': 'class method', 'path': 'dom/element/nextsiblings' }, +'Object.values': { 'name': 'Object.values', 'type': 'class method', 'path': 'language/object/values' }, +'String#escapeHTML': { 'name': 'String#escapeHTML', 'type': 'instance method', 'path': 'language/string/prototype/escapehtml' }, +'Enumerable#max': { 'name': 'Enumerable#max', 'type': 'instance method', 'path': 'language/enumerable/prototype/max' }, +'Ajax.PeriodicalUpdater': { 'name': 'Ajax.PeriodicalUpdater', 'type': 'class', 'path': 'ajax/ajax/periodicalupdater' }, +'Form.serializeElements': { 'name': 'Form.serializeElements', 'type': 'class method', 'path': 'dom/form/serializeelements' }, +'Hash#set': { 'name': 'Hash#set', 'type': 'instance method', 'path': 'language/hash/prototype/set' }, +'Date#toJSON': { 'name': 'Date#toJSON', 'type': 'instance method', 'path': 'language/date/prototype/tojson' }, +'Form.Element#clear': { 'name': 'Form.Element#clear', 'type': 'instance method', 'path': 'dom/form/element/prototype/clear' }, +'Array#without': { 'name': 'Array#without', 'type': 'instance method', 'path': 'language/array/prototype/without' }, +'Form.Observer': { 'name': 'Form.Observer', 'type': 'class', 'path': 'dom/form/observer' }, +'Hash': { 'name': 'Hash', 'type': 'class', 'path': 'language/hash' }, +'new Form.Element.Observer': { 'name': 'new Form.Element.Observer', 'type': 'constructor', 'path': 'dom/form/element/observer/new' }, +'Element#toggleClassName': { 'name': 'Element#toggleClassName', 'type': 'instance method', 'path': 'dom/element/prototype/toggleclassname' }, +'Selector.findElement': { 'name': 'Selector.findElement', 'type': 'class method', 'path': 'dom/selector/findelement' }, +'Array#reverse': { 'name': 'Array#reverse', 'type': 'instance method', 'path': 'language/array/prototype/reverse' }, +'new Hash': { 'name': 'new Hash', 'type': 'constructor', 'path': 'language/hash/new' }, +'Enumerable#eachSlice': { 'name': 'Enumerable#eachSlice', 'type': 'instance method', 'path': 'language/enumerable/prototype/eachslice' }, +'Element.siblings': { 'name': 'Element.siblings', 'type': 'class method', 'path': 'dom/element/siblings' }, +'ObjectRange#include': { 'name': 'ObjectRange#include', 'type': 'instance method', 'path': 'language/objectrange/prototype/include' }, +'Number#toPaddedString': { 'name': 'Number#toPaddedString', 'type': 'instance method', 'path': 'language/number/prototype/topaddedstring' }, +'Form#getInputs': { 'name': 'Form#getInputs', 'type': 'instance method', 'path': 'dom/form/prototype/getinputs' }, +'Element.wrap': { 'name': 'Element.wrap', 'type': 'class method', 'path': 'dom/element/wrap' }, +'Form#disable': { 'name': 'Form#disable', 'type': 'instance method', 'path': 'dom/form/prototype/disable' }, +'Hash#values': { 'name': 'Hash#values', 'type': 'instance method', 'path': 'language/hash/prototype/values' }, +'Element#viewportOffset': { 'name': 'Element#viewportOffset', 'type': 'instance method', 'path': 'dom/element/prototype/viewportoffset' }, +'Element#ancestors': { 'name': 'Element#ancestors', 'type': 'instance method', 'path': 'dom/element/prototype/ancestors' }, +'Element.immediateDescendants': { 'name': 'Element.immediateDescendants', 'type': 'class method', 'path': 'dom/element/immediatedescendants' }, +'Form.Element#disable': { 'name': 'Form.Element#disable', 'type': 'instance method', 'path': 'dom/form/element/prototype/disable' }, +'Hash#toObject': { 'name': 'Hash#toObject', 'type': 'instance method', 'path': 'language/hash/prototype/toobject' }, +'Event.stop': { 'name': 'Event.stop', 'type': 'class method', 'path': 'dom/event/stop' }, +'Ajax.Request#getHeader': { 'name': 'Ajax.Request#getHeader', 'type': 'instance method', 'path': 'ajax/ajax/request/prototype/getheader' }, +'Element#scrollTo': { 'name': 'Element#scrollTo', 'type': 'instance method', 'path': 'dom/element/prototype/scrollto' }, +'Form': { 'name': 'Form', 'type': 'namespace', 'path': 'dom/form' }, +'Element#childElements': { 'name': 'Element#childElements', 'type': 'instance method', 'path': 'dom/element/prototype/childelements' }, +'Element#getStorage': { 'name': 'Element#getStorage', 'type': 'instance method', 'path': 'dom/element/prototype/getstorage' }, +'String#isJSON': { 'name': 'String#isJSON', 'type': 'instance method', 'path': 'language/string/prototype/isjson' }, +'Event.element': { 'name': 'Event.element', 'type': 'class method', 'path': 'dom/event/element' }, +'new Abstract.TimedObserver': { 'name': 'new Abstract.TimedObserver', 'type': 'constructor', 'path': 'dom/abstract/timedobserver/new' }, +'Object.isUndefined': { 'name': 'Object.isUndefined', 'type': 'class method', 'path': 'language/object/isundefined' }, +'Function#argumentNames': { 'name': 'Function#argumentNames', 'type': 'instance method', 'path': 'language/function/prototype/argumentnames' }, +'Ajax.Response#transport': { 'name': 'Ajax.Response#transport', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/transport' }, +'Ajax.activeRequestCount': { 'name': 'Ajax.activeRequestCount', 'type': 'class property', 'path': 'ajax/ajax/activerequestcount' }, +'document.observe': { 'name': 'document.observe', 'type': 'class method', 'path': 'dom/document/observe' }, +'Enumerable#each': { 'name': 'Enumerable#each', 'type': 'instance method', 'path': 'language/enumerable/prototype/each' }, +'String#toArray': { 'name': 'String#toArray', 'type': 'instance method', 'path': 'language/string/prototype/toarray' }, +'Object.keys': { 'name': 'Object.keys', 'type': 'class method', 'path': 'language/object/keys' }, +'Element#readAttribute': { 'name': 'Element#readAttribute', 'type': 'instance method', 'path': 'dom/element/prototype/readattribute' }, +'Element.retrieve': { 'name': 'Element.retrieve', 'type': 'class method', 'path': 'dom/element/retrieve' }, +'Class#addMethods': { 'name': 'Class#addMethods', 'type': 'instance method', 'path': 'language/class/prototype/addmethods' }, +'Ajax.Response#getAllHeaders': { 'name': 'Ajax.Response#getAllHeaders', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getallheaders' }, +'Enumerable#inGroupsOf': { 'name': 'Enumerable#inGroupsOf', 'type': 'instance method', 'path': 'language/enumerable/prototype/ingroupsof' }, +'Event#isRightClick': { 'name': 'Event#isRightClick', 'type': 'instance method', 'path': 'dom/event/prototype/isrightclick' }, +'Array#lastIndexOf': { 'name': 'Array#lastIndexOf', 'type': 'instance method', 'path': 'language/array/prototype/lastindexof' }, +'Function#methodize': { 'name': 'Function#methodize', 'type': 'instance method', 'path': 'language/function/prototype/methodize' }, +'$$': { 'name': '$$', 'type': 'utility', 'path': 'dollardollar' }, +'Element#absolutize': { 'name': 'Element#absolutize', 'type': 'instance method', 'path': 'dom/element/prototype/absolutize' }, +'Object.isFunction': { 'name': 'Object.isFunction', 'type': 'class method', 'path': 'language/object/isfunction' }, +'Element.undoClipping': { 'name': 'Element.undoClipping', 'type': 'class method', 'path': 'dom/element/undoclipping' }, +'Element.childElements': { 'name': 'Element.childElements', 'type': 'class method', 'path': 'dom/element/childelements' }, +'Form.Element.select': { 'name': 'Form.Element.select', 'type': 'class method', 'path': 'dom/form/element/select' }, +'Ajax': { 'name': 'Ajax', 'type': 'namespace', 'path': 'ajax/ajax' }, +'Element#undoClipping': { 'name': 'Element#undoClipping', 'type': 'instance method', 'path': 'dom/element/prototype/undoclipping' }, +'Element#match': { 'name': 'Element#match', 'type': 'instance method', 'path': 'dom/element/prototype/match' }, +'Form.Element.enable': { 'name': 'Form.Element.enable', 'type': 'class method', 'path': 'dom/form/element/enable' }, +'Enumerable#min': { 'name': 'Enumerable#min', 'type': 'instance method', 'path': 'language/enumerable/prototype/min' }, +'String#stripTags': { 'name': 'String#stripTags', 'type': 'instance method', 'path': 'language/string/prototype/striptags' }, +'Number#times': { 'name': 'Number#times', 'type': 'instance method', 'path': 'language/number/prototype/times' }, +'Element.scrollTo': { 'name': 'Element.scrollTo', 'type': 'class method', 'path': 'dom/element/scrollto' }, +'Event.isLeftClick': { 'name': 'Event.isLeftClick', 'type': 'class method', 'path': 'dom/event/isleftclick' }, +'Element#identify': { 'name': 'Element#identify', 'type': 'instance method', 'path': 'dom/element/prototype/identify' }, +'document.viewport': { 'name': 'document.viewport', 'type': 'namespace', 'path': 'dom/document/viewport' }, +'Array#toArray': { 'name': 'Array#toArray', 'type': 'instance method', 'path': 'language/array/prototype/toarray' }, +'Element#clonePosition': { 'name': 'Element#clonePosition', 'type': 'instance method', 'path': 'dom/element/prototype/cloneposition' }, +'Object.isArray': { 'name': 'Object.isArray', 'type': 'class method', 'path': 'language/object/isarray' }, +'Selector.matchElements': { 'name': 'Selector.matchElements', 'type': 'class method', 'path': 'dom/selector/matchelements' }, +'Object.inspect': { 'name': 'Object.inspect', 'type': 'class method', 'path': 'language/object/inspect' }, +'String#inspect': { 'name': 'String#inspect', 'type': 'instance method', 'path': 'language/string/prototype/inspect' }, +'Array#size': { 'name': 'Array#size', 'type': 'instance method', 'path': 'language/array/prototype/size' }, +'Ajax.Response#responseText': { 'name': 'Ajax.Response#responseText', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsetext' }, +'Element#getStyle': { 'name': 'Element#getStyle', 'type': 'instance method', 'path': 'dom/element/prototype/getstyle' }, +'Ajax.Response#responseJSON': { 'name': 'Ajax.Response#responseJSON', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsejson' }, +'Element#insert': { 'name': 'Element#insert', 'type': 'instance method', 'path': 'dom/element/prototype/insert' }, +'new Ajax.Updater': { 'name': 'new Ajax.Updater', 'type': 'constructor', 'path': 'ajax/ajax/updater/new' }, +'Selector#match': { 'name': 'Selector#match', 'type': 'instance method', 'path': 'dom/selector/prototype/match' }, +'String#parseQuery': { 'name': 'String#parseQuery', 'type': 'instance method', 'path': 'language/string/prototype/parsequery' }, +'Ajax.Response#readyState': { 'name': 'Ajax.Response#readyState', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/readystate' }, +'Enumerable#filter': { 'name': 'Enumerable#filter', 'type': 'instance method', 'path': 'language/enumerable/prototype/filter' }, +'Form.focusFirstElement': { 'name': 'Form.focusFirstElement', 'type': 'class method', 'path': 'dom/form/focusfirstelement' }, +'Ajax.Response#headerJSON': { 'name': 'Ajax.Response#headerJSON', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/headerjson' }, +'Number#toJSON': { 'name': 'Number#toJSON', 'type': 'instance method', 'path': 'language/number/prototype/tojson' }, +'Form#enable': { 'name': 'Form#enable', 'type': 'instance method', 'path': 'dom/form/prototype/enable' }, +'Form.Element#activate': { 'name': 'Form.Element#activate', 'type': 'instance method', 'path': 'dom/form/element/prototype/activate' }, +'Event#pointerX': { 'name': 'Event#pointerX', 'type': 'instance method', 'path': 'dom/event/prototype/pointerx' }, +'Object.extend': { 'name': 'Object.extend', 'type': 'class method', 'path': 'language/object/extend' }, +'DOM section': { 'name': 'DOM section', 'type': 'section', 'path': 'dom' }, +'document.viewport.getWidth': { 'name': 'document.viewport.getWidth', 'type': 'class method', 'path': 'dom/document/viewport/getwidth' }, +'Element.getOffsetParent': { 'name': 'Element.getOffsetParent', 'type': 'class method', 'path': 'dom/element/getoffsetparent' }, +'Object.toJSON': { 'name': 'Object.toJSON', 'type': 'class method', 'path': 'language/object/tojson' }, +'PeriodicalExecuter#stop': { 'name': 'PeriodicalExecuter#stop', 'type': 'instance method', 'path': 'language/periodicalexecuter/prototype/stop' }, +'Function#bindAsEventListener': { 'name': 'Function#bindAsEventListener', 'type': 'instance method', 'path': 'language/function/prototype/bindaseventlistener' }, +'Event#pointerY': { 'name': 'Event#pointerY', 'type': 'instance method', 'path': 'dom/event/prototype/pointery' }, +'Ajax.Response': { 'name': 'Ajax.Response', 'type': 'class', 'path': 'ajax/ajax/response' }, +'Hash#toJSON': { 'name': 'Hash#toJSON', 'type': 'instance method', 'path': 'language/hash/prototype/tojson' }, +'Hash#keys': { 'name': 'Hash#keys', 'type': 'instance method', 'path': 'language/hash/prototype/keys' }, +'Element#store': { 'name': 'Element#store', 'type': 'instance method', 'path': 'dom/element/prototype/store' }, +'Element.replace': { 'name': 'Element.replace', 'type': 'class method', 'path': 'dom/element/replace' }, +'Element.descendants': { 'name': 'Element.descendants', 'type': 'class method', 'path': 'dom/element/descendants' }, +'Ajax.Response.getResponseHeader': { 'name': 'Ajax.Response.getResponseHeader', 'type': 'class method', 'path': 'ajax/ajax/response/getresponseheader' }, +'Enumerable#reject': { 'name': 'Enumerable#reject', 'type': 'instance method', 'path': 'language/enumerable/prototype/reject' }, +'Enumerable#some': { 'name': 'Enumerable#some', 'type': 'instance method', 'path': 'language/enumerable/prototype/some' }, +'Enumerable#partition': { 'name': 'Enumerable#partition', 'type': 'instance method', 'path': 'language/enumerable/prototype/partition' }, +'Hash#update': { 'name': 'Hash#update', 'type': 'instance method', 'path': 'language/hash/prototype/update' }, +'Form#focusFirstElement': { 'name': 'Form#focusFirstElement', 'type': 'instance method', 'path': 'dom/form/prototype/focusfirstelement' }, +'Element#previousSiblings': { 'name': 'Element#previousSiblings', 'type': 'instance method', 'path': 'dom/element/prototype/previoussiblings' }, +'Element.clonePosition': { 'name': 'Element.clonePosition', 'type': 'class method', 'path': 'dom/element/cloneposition' }, +'Ajax.Response#status': { 'name': 'Ajax.Response#status', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/status' }, +'Element#nextSiblings': { 'name': 'Element#nextSiblings', 'type': 'instance method', 'path': 'dom/element/prototype/nextsiblings' }, +'Number#succ': { 'name': 'Number#succ', 'type': 'instance method', 'path': 'language/number/prototype/succ' }, +'Element#update': { 'name': 'Element#update', 'type': 'instance method', 'path': 'dom/element/prototype/update' }, +'Element#stopObserving': { 'name': 'Element#stopObserving', 'type': 'instance method', 'path': 'dom/element/prototype/stopobserving' }, +'Element.identify': { 'name': 'Element.identify', 'type': 'class method', 'path': 'dom/element/identify' }, +'document.viewport.getHeight': { 'name': 'document.viewport.getHeight', 'type': 'class method', 'path': 'dom/document/viewport/getheight' }, +'Try.these': { 'name': 'Try.these', 'type': 'class method', 'path': 'language/try/these' }, +'Element#adjacent': { 'name': 'Element#adjacent', 'type': 'instance method', 'path': 'dom/element/prototype/adjacent' }, +'Enumerable#size': { 'name': 'Enumerable#size', 'type': 'instance method', 'path': 'language/enumerable/prototype/size' }, +'new Ajax.Request': { 'name': 'new Ajax.Request', 'type': 'constructor', 'path': 'ajax/ajax/request/new' }, +'Function#wrap': { 'name': 'Function#wrap', 'type': 'instance method', 'path': 'language/function/prototype/wrap' }, +'document.loaded': { 'name': 'document.loaded', 'type': 'class property', 'path': 'dom/document/loaded' }, +'Element#classNames': { 'name': 'Element#classNames', 'type': 'instance method', 'path': 'dom/element/prototype/classnames' }, +'Element#empty': { 'name': 'Element#empty', 'type': 'instance method', 'path': 'dom/element/prototype/empty' }, +'Function#defer': { 'name': 'Function#defer', 'type': 'instance method', 'path': 'language/function/prototype/defer' }, +'Array#intersect': { 'name': 'Array#intersect', 'type': 'instance method', 'path': 'language/array/prototype/intersect' }, +'Element.previousSiblings': { 'name': 'Element.previousSiblings', 'type': 'class method', 'path': 'dom/element/previoussiblings' }, +'new Template': { 'name': 'new Template', 'type': 'constructor', 'path': 'language/template/new' }, +'Enumerable#findAll': { 'name': 'Enumerable#findAll', 'type': 'instance method', 'path': 'language/enumerable/prototype/findall' }, +'Form.reset': { 'name': 'Form.reset', 'type': 'class method', 'path': 'dom/form/reset' }, +'Function#curry': { 'name': 'Function#curry', 'type': 'instance method', 'path': 'language/function/prototype/curry' } +}; \ No newline at end of file diff --git a/doc/1.6.1/javascripts/prototype.js b/doc/1.6.1/javascripts/prototype.js new file mode 100644 index 000000000..9fe6e1243 --- /dev/null +++ b/doc/1.6.1/javascripts/prototype.js @@ -0,0 +1,4874 @@ +/* Prototype JavaScript framework, version 1.6.1 + * (c) 2005-2009 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.6.1', + + Browser: (function(){ + var ua = navigator.userAgent; + var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; + return { + IE: !!window.attachEvent && !isOpera, + Opera: isOpera, + WebKit: ua.indexOf('AppleWebKit/') > -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile.*Safari/.test(ua) + } + })(), + + BrowserFeatures: { + XPath: !!document.evaluate, + SelectorsAPI: !!document.querySelector, + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'); + var form = document.createElement('form'); + var isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + + +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +/* Based on Alex Arnell's inheritance implementation. */ + +var Class = (function() { + function subclass() {}; + function create() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value; + value = (function(m) { + return function() { return ancestor[m].apply(this, arguments); }; + })(property).wrap(method); + + value.valueOf = method.valueOf.bind(method); + value.toString = method.toString.bind(method); + } + this.prototype[property] = value; + } + + return this; + } + + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { + + var _toString = Object.prototype.toString; + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } + + function inspect(object) { + try { + if (isUndefined(object)) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : String(object); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + } + + function toJSON(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (isElement(object)) return; + + var results = []; + for (var property in object) { + var value = toJSON(object[property]); + if (!isUndefined(value)) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + } + + function toQueryString(object) { + return $H(object).toQueryString(); + } + + function toHTML(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + } + + function keys(object) { + var results = []; + for (var property in object) + results.push(property); + return results; + } + + function values(object) { + var results = []; + for (var property in object) + results.push(object[property]); + return results; + } + + function clone(object) { + return extend({ }, object); + } + + function isElement(object) { + return !!(object && object.nodeType == 1); + } + + function isArray(object) { + return _toString.call(object) == "[object Array]"; + } + + + function isHash(object) { + return object instanceof Hash; + } + + function isFunction(object) { + return typeof object === "function"; + } + + function isString(object) { + return _toString.call(object) == "[object String]"; + } + + function isNumber(object) { + return _toString.call(object) == "[object Number]"; + } + + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function() { + var a = merge(args, arguments); + return __method.apply(context, a); + } + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function(event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + } + } + + function curry() { + if (!arguments.length) return this; + var __method = this, args = slice.call(arguments, 0); + return function() { + var a = merge(args, arguments); + return __method.apply(this, a); + } + } + + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000 + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + } + + function defer() { + var args = update([0.01], arguments); + return this.delay.apply(this, args); + } + + function wrap(wrapper) { + var __method = this; + return function() { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + } + } + + function methodize() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + var a = update([this], arguments); + return __method.apply(null, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, (function() { + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { + var result = '', source = this, match; + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + } + + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); + count = Object.isUndefined(count) ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + } + + function scan(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + } + + function truncate(length, truncation) { + length = length || 30; + truncation = Object.isUndefined(truncation) ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + } + + function strip() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + } + + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } + + function stripScripts() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + } + + function extractScripts() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + } + + function evalScripts() { + return this.extractScripts().map(function(script) { return eval(script) }); + } + + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } + + + function toQueryParams(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + } + + function toArray() { + return this.split(''); + } + + function succ() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + } + + function times(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + } + + function camelize() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + } + + function capitalize() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + } + + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } + + function dasherize() { + return this.replace(/_/g, '-'); + } + + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } + + function toJSON() { + return this.inspect(true); + } + + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } + + function isJSON() { + var str = this; + if (str.blank()) return false; + str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + } + + function evalJSON(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + } + + function include(pattern) { + return this.indexOf(pattern) > -1; + } + + function startsWith(pattern) { + return this.indexOf(pattern) === 0; + } + + function endsWith(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + } + + function empty() { + return this == ''; + } + + function blank() { + return /^\s*$/.test(this); + } + + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); + } + + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim ? String.prototype.trim : strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + toJSON: toJSON, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (object && Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return (match[1] + ''); + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = (function() { + function each(iterator, context) { + var index = 0; + try { + this._each(function(value) { + iterator.call(context, value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + } + + function eachSlice(number, iterator, context) { + var index = -number, slices = [], array = this.toArray(); + if (number < 1) return array; + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + } + + function all(iterator, context) { + iterator = iterator || Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator.call(context, value, index); + if (!result) throw $break; + }); + return result; + } + + function any(iterator, context) { + iterator = iterator || Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator.call(context, value, index)) + throw $break; + }); + return result; + } + + function collect(iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function detect(iterator, context) { + var result; + this.each(function(value, index) { + if (iterator.call(context, value, index)) { + result = value; + throw $break; + } + }); + return result; + } + + function findAll(iterator, context) { + var results = []; + this.each(function(value, index) { + if (iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function grep(filter, iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(RegExp.escape(filter)); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function include(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + } + + function inGroupsOf(number, fillWith) { + fillWith = Object.isUndefined(fillWith) ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + } + + function inject(memo, iterator, context) { + this.each(function(value, index) { + memo = iterator.call(context, memo, value, index); + }); + return memo; + } + + function invoke(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + } + + function max(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value >= result) + result = value; + }); + return result; + } + + function min(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value < result) + result = value; + }); + return result; + } + + function partition(iterator, context) { + iterator = iterator || Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator.call(context, value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + } + + function pluck(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + } + + function reject(iterator, context) { + var results = []; + this.each(function(value, index) { + if (!iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function sortBy(iterator, context) { + return this.map(function(value, index) { + return { + value: value, + criteria: iterator.call(context, value, index) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + } + + function toArray() { + return this.map(); + } + + function zip() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + } + + function size() { + return this.toArray().length; + } + + function inspect() { + return '#'; + } + + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); +function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +Array.from = $A; + + +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available + + function each(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + } + if (!_each) _each = each; + + function clear() { + this.length = 0; + return this; + } + + function first() { + return this[0]; + } + + function last() { + return this[this.length - 1]; + } + + function compact() { + return this.select(function(value) { + return value != null; + }); + } + + function flatten() { + return this.inject([], function(array, value) { + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; + }); + } + + function without() { + var values = slice.call(arguments, 0); + return this.select(function(value) { + return !values.include(value); + }); + } + + function reverse(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + } + + function uniq(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + } + + function intersect(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + } + + + function clone() { + return slice.call(this, 0); + } + + function size() { + return this.length; + } + + function inspect() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } + + function toJSON() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (!Object.isUndefined(value)) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } + + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } + + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } + + function concat() { + var array = slice.call(this, 0), item; + for (var i = 0, length = arguments.length; i < length; i++) { + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); + } else { + array.push(item); + } + } + return array; + } + + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); + + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) + + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; + + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } + + function inspect() { + return '#'; + } + + function toJSON() { + return Object.toJSON(this.toObject()); + } + + function clone() { + return new Hash(this); + } + + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; +})()); + +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } + + function succ() { + return this + 1; + } + + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } + + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } + + function toJSON() { + return isFinite(this) ? this.toString() : 'null'; + } + + function abs() { + return Math.abs(this); + } + + function round() { + return Math.round(this); + } + + function ceil() { + return Math.ceil(this); + } + + function floor() { + return Math.floor(this); + } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + toJSON: toJSON, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; +})()); + +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + } + + function _each(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + } + + function include(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } + + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); + } +}); +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name) || null; + } catch (e) { return null; } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); + + + +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +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(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + + +(function(global) { + + var SETATTRIBUTE_IGNORES_NAME = (function(){ + var elForm = document.createElement("form"); + var elInput = document.createElement("input"); + var root = document.documentElement; + elInput.setAttribute("name", "test"); + elForm.appendChild(elInput); + root.appendChild(elForm); + var isBuggy = elForm.elements + ? (typeof elForm.elements.test == "undefined") + : null; + root.removeChild(elForm); + elForm = elInput = null; + return isBuggy; + })(); + + var element = global.Element; + global.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; +})(this); + +Element.cache = { }; +Element.idCounter = 1; + +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 = $(element); + element.style.display = 'none'; + return element; + }, + + show: function(element) { + element = $(element); + element.style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return Element.recursivelyCollect(element, 'parentNode'); + }, + + descendants: function(element) { + return Element.select(element, "*"); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return Element.recursivelyCollect(element, 'previousSibling'); + }, + + nextSiblings: function(element) { + return Element.recursivelyCollect(element, 'nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + 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(element); + return Object.isNumber(expression) ? ancestors[expression] : + Selector.findElement(ancestors, expression, index); + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = Element.previousSiblings(element); + return Object.isNumber(expression) ? previousSiblings[expression] : + Selector.findElement(previousSiblings, expression, index); + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = Element.nextSiblings(element); + return Object.isNumber(expression) ? nextSiblings[expression] : + Selector.findElement(nextSiblings, expression, index); + }, + + + select: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element, args); + }, + + adjacent: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = Element.readAttribute(element, 'id'); + if (id) return id; + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return Element.getDimensions(element).height; + }, + + getWidth: function(element) { + return Element.getDimensions(element).width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!Element.hasClassName(element, className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (ancestor.contains) + return ancestor.contains(element) && ancestor !== element; + + while (element = element.parentNode) + if (element == ancestor) return true; + + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Element.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 || value == 'auto') { + 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) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = Element.getStyle(element, 'display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + if (Prototype.Browser.Opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName.toUpperCase() == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'absolute') return element; + + var offsets = Element.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'relative') return element; + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + source = $(source); + var p = Element.viewportOffset(source); + + element = $(element); + var delta = [0, 0]; + var parent = null; + if (Element.getStyle(element, 'position') == 'absolute') { + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); + } + + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + +if (Prototype.Browser.Opera) { + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + if (!Element.visible(element)) return null; + + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } + } + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); +} + +else if (Prototype.Browser.IE) { + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return $(document.body) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( + function(proceed, element) { + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + return proceed(element); + } + ); + + 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) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = (function(){ + + var classProp = 'className'; + var forProp = 'for'; + + var el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'); + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + var f; + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + } + })(); + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr2, + src: v._getAttr2, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName.toUpperCase() == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if ('outerHTML' in document.documentElement) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + } else div.innerHTML = html; + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['', '
    ', 1], + TBODY: ['', '
    ', 2], + TR: ['', '
    ', 3], + TD: ['
    ', '
    ', 4], + SELECT: ['', 1] + } +}; + +(function() { + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD + }); +})(); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return !!(node && node.specified); + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')) + +Element.extend = (function() { + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2); + var el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } + return Prototype.K; + } + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || typeof element._extendedByPrototype != 'undefined' || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName.toUpperCase(); + + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + extendElementWith(element, methods); + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +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, { + "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 (Object.isArray(tagName)) 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; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + 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]; + + var element = document.createElement(tagName); + var proto = element['__proto__'] || element.constructor.prototype; + element = null; + return proto; + } + + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + + if (F.ElementExtensions) { + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + + +document.viewport = { + + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = [Element.Storage.UID++]; + uid = element._prototypeUID[0]; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + } +}); +/* Portions of the Selector class are derived from Jack Slocum's DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + + if (this.shouldUseSelectorsAPI()) { + this.mode = 'selectorsAPI'; + } else if (this.shouldUseXPath()) { + this.mode = 'xpath'; + this.compileXPathMatcher(); + } else { + this.mode = "normal"; + this.compileMatcher(); + } + + }, + + shouldUseXPath: (function() { + + var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ + var isBuggy = false; + if (document.evaluate && window.XPathResult) { + var el = document.createElement('div'); + el.innerHTML = '
    '; + + var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; + + var result = document.evaluate(xpath, el, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + + isBuggy = (result.snapshotLength !== 2); + el = null; + } + return isBuggy; + })(); + + return function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + if (IS_DESCENDANT_SELECTOR_BUGGY) return false; + + return true; + } + + })(), + + shouldUseSelectorsAPI: function() { + if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + + if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; + + if (!Selector._div) Selector._div = new Element('div'); + + try { + Selector._div.querySelector(this.expression); + } catch(e) { + return false; + } + + return true; + }, + + compileMatcher: function() { + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m, len = ps.length, name; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i"; + } +}); + +if (Prototype.BrowserFeatures.SelectorsAPI && + document.compatMode === 'BackCompat') { + Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ + var div = document.createElement('div'), + span = document.createElement('span'); + + div.id = "prototype_test_id"; + span.className = 'Test'; + div.appendChild(span); + var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); + div = span = null; + return isIgnored; + })(); +} + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: function(m) { + m[1] = m[1].toLowerCase(); + return new Template("[@#{1}]").evaluate(m); + }, + attr: function(m) { + m[1] = m[1].toLowerCase(); + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0)]", + 'checked': "[@checked]", + 'disabled': "[(@disabled) and (@type!='hidden')]", + 'enabled': "[not(@disabled) and (@type!='hidden')]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, v, len = p.length, name; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: [ + { name: 'laterSibling', re: /^\s*~\s*/ }, + { name: 'child', re: /^\s*>\s*/ }, + { name: 'adjacent', re: /^\s*\+\s*/ }, + { name: 'descendant', re: /^\s/ }, + + { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, + { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, + { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, + { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, + { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, + { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } + ], + + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); + } + }, + + handlers: { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + mark: function(nodes) { + var _true = Prototype.emptyFunction; + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = _true; + return nodes; + }, + + unmark: (function(){ + + var PROPERTIES_ATTRIBUTES_MAP = (function(){ + var el = document.createElement('div'), + isBuggy = false, + propName = '_countedByPrototype', + value = 'x' + el[propName] = value; + isBuggy = (el.getAttribute(propName) === value); + el = null; + return isBuggy; + })(); + + return PROPERTIES_ATTRIBUTES_MAP ? + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } : + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = void 0; + return nodes; + } + })(), + + index: function(parentNode, reverse, ofType) { + parentNode._countedByPrototype = Prototype.emptyFunction; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + }, + + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { + n._countedByPrototype = Prototype.emptyFunction; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + tagName: function(nodes, root, tagName, combinator) { + var uTagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() === uTagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + + if (root == document) { + if (!targetNode) return []; + if (!nodes) return [targetNode]; + } else { + if (!root.sourceIndex || root.sourceIndex < 1) { + var nodes = root.getElementsByTagName('*'); + for (var j = 0, node; node = nodes[j]; j++) { + if (node.id === id) return [node]; + } + } + } + + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._countedByPrototype) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (node.tagName == '!' || node.firstChild) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._countedByPrototype) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled && (!node.type || node.type !== 'hidden')) + results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, + '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, + '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + + '-').include('-' + (v || "").toUpperCase() + '-'); } + }, + + split: function(expression) { + var expressions = []; + expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + return expressions; + }, + + matchElements: function(elements, expression) { + var matches = $$(expression), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._countedByPrototype) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + expressions = Selector.split(expressions.join(',')); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +if (Prototype.Browser.IE) { + Object.extend(Selector.handlers, { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + if (node.tagName !== "!") a.push(node); + return a; + } + }); +} + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} + +var Form = { + reset: function(form) { + form = $(form); + form.reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return /^(?:input|select|textarea)$/i.test(element.tagName); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !(/^(?:button|reset|submit)$/i.test(element.type)))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; + +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; + }, + + select: function(element, value) { + if (Object.isUndefined(value)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, currentValue, single = !Object.isArray(value); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + currentValue = this.optionValue(opt); + if (single) { + if (currentValue == value) { + opt.selected = true; + return; + } + } + else opt.selected = value.include(currentValue); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +(function() { + + var Event = { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; + + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + + var _isButton; + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + _isButton = function(event, code) { + return event.button === buttonMap[code]; + }; + } else if (Prototype.Browser.WebKit) { + _isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + } else { + _isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + function isLeftClick(event) { return _isButton(event, 0) } + + function isMiddleClick(event) { return _isButton(event, 1) } + + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); + + var node = event.target, type = event.type, + currentTarget = event.currentTarget; + + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; + } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop + }; + + + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return '[object Event]' } + }); + + Event.extend = function(event, element) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + + Object.extend(event, { + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + + return Object.extend(event, methods); + }; + } else { + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; + Object.extend(Event.prototype, methods); + Event.extend = Prototype.K; + } + + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } + + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } + + if (respondersForEvent.pluck('handler').include(handler)) return false; + + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; + + if (event.eventName !== eventName) + return false; + + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } + + if (parent === element) return; + + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } + + responder.handler = handler; + respondersForEvent.push(responder); + return responder; + } + + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } + } + + var CACHE = []; + + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); + + if (Prototype.Browser.WebKit) + window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; + } + + function observe(element, eventName, handler) { + element = $(element); + + var responder = _createResponder(element, eventName, handler); + + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); + } + } else { + var actualEventName = _getDOMEventName(eventName); + + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } + + return element; + } + + function stopObserving(element, eventName, handler) { + element = $(element); + + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) return element; + + if (eventName && !handler) { + var responders = registry.get(eventName); + + if (Object.isUndefined(responders)) return element; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + return element; + } else if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key, responders = pair.value; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + }); + return element; + } + + var responders = registry.get(eventName); + + if (!responders) return; + + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + var actualEventName = _getDOMEventName(eventName); + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); + } + } else { + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; + + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); + + return Event.extend(event); + } + + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ + + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearTimeout(timer); + document.loaded = true; + document.fire('dom:loaded'); + } + + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } + + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; + } + fireContentLoadedEvent(); + } + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); + } else { + document.observe('readystatechange', checkReadyState); + if (window == top) + timer = pollDoScroll.defer(); + } + + Event.observe(window, 'load', fireContentLoadedEvent); +})(); + +Element.addMethods(); + +/*------------------------------- DEPRECATED -------------------------------*/ + +Hash.toQueryString = Object.toQueryString; + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); + }, + + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, + + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, + + After: function(element, content) { + return Element.insert(element, {after:content}); + } +}; + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Position = { + includeScrollOffsets: false, + + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +/*--------------------------------------------------------------------------*/ + +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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); + +/*--------------------------------------------------------------------------*/ diff --git a/doc/1.6.1/javascripts/tabs.js b/doc/1.6.1/javascripts/tabs.js new file mode 100644 index 000000000..7c974209f --- /dev/null +++ b/doc/1.6.1/javascripts/tabs.js @@ -0,0 +1,506 @@ +/** + * @author Ryan Johnson + * @copyright 2008 PersonalGrid Corporation + * @package LivePipe UI + * @license MIT + * @url http://livepipe.net/core + * @require prototype.js + */ + +if(typeof(Control) == 'undefined') + Control = {}; + +var $proc = function(proc){ + return typeof(proc) == 'function' ? proc : function(){return proc}; +}; + +var $value = function(value){ + return typeof(value) == 'function' ? value() : value; +}; + +Object.Event = { + extend: function(object){ + object._objectEventSetup = function(event_name){ + this._observers = this._observers || {}; + this._observers[event_name] = this._observers[event_name] || []; + }; + object.observe = function(event_name,observer){ + if(typeof(event_name) == 'string' && typeof(observer) != 'undefined'){ + this._objectEventSetup(event_name); + if(!this._observers[event_name].include(observer)) + this._observers[event_name].push(observer); + }else + for(var e in event_name) + this.observe(e,event_name[e]); + }; + object.stopObserving = function(event_name,observer){ + this._objectEventSetup(event_name); + if(event_name && observer) + this._observers[event_name] = this._observers[event_name].without(observer); + else if(event_name) + this._observers[event_name] = []; + else + this._observers = {}; + }; + object.observeOnce = function(event_name,outer_observer){ + var inner_observer = function(){ + outer_observer.apply(this,arguments); + this.stopObserving(event_name,inner_observer); + }.bind(this); + this._objectEventSetup(event_name); + this._observers[event_name].push(inner_observer); + }; + object.notify = function(event_name){ + this._objectEventSetup(event_name); + var collected_return_values = []; + var args = $A(arguments).slice(1); + try{ + for(var i = 0; i < this._observers[event_name].length; ++i) + collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null); + }catch(e){ + if(e == $break) + return false; + else + throw e; + } + return collected_return_values; + }; + if(object.prototype){ + object.prototype._objectEventSetup = object._objectEventSetup; + object.prototype.observe = object.observe; + object.prototype.stopObserving = object.stopObserving; + object.prototype.observeOnce = object.observeOnce; + object.prototype.notify = function(event_name){ + if(object.notify){ + var args = $A(arguments).slice(1); + args.unshift(this); + args.unshift(event_name); + object.notify.apply(object,args); + } + this._objectEventSetup(event_name); + var args = $A(arguments).slice(1); + var collected_return_values = []; + try{ + if(this.options && this.options[event_name] && typeof(this.options[event_name]) == 'function') + collected_return_values.push(this.options[event_name].apply(this,args) || null); + for(var i = 0; i < this._observers[event_name].length; ++i) + collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null); + }catch(e){ + if(e == $break) + return false; + else + throw e; + } + return collected_return_values; + }; + } + } +}; + +/* Begin Core Extensions */ + +//Element.observeOnce +Element.addMethods({ + observeOnce: function(element,event_name,outer_callback){ + var inner_callback = function(){ + outer_callback.apply(this,arguments); + Element.stopObserving(element,event_name,inner_callback); + }; + Element.observe(element,event_name,inner_callback); + } +}); + +//mouseenter, mouseleave +//from http://dev.rubyonrails.org/attachment/ticket/8354/event_mouseenter_106rc1.patch +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._prototypeEventID) return element._prototypeEventID[0]; + arguments.callee.id = arguments.callee.id || 1; + return element._prototypeEventID = [++arguments.callee.id]; + } + + function getDOMEventName(eventName) { + if (eventName && eventName.include(':')) return "dataavailable"; + //begin extension + if(!Prototype.Browser.IE){ + eventName = { + mouseenter: 'mouseover', + mouseleave: 'mouseout' + }[eventName] || eventName; + } + //end extension + return eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(element, eventName, handler) { + var id = getEventID(element); + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (!Event || !Event.extend || + (event.eventName && event.eventName != eventName)) + return false; + + Event.extend(event); + handler.call(element, event); + }; + + //begin extension + if(!(Prototype.Browser.IE) && ['mouseenter','mouseleave'].include(eventName)){ + wrapper = wrapper.wrap(function(proceed,event) { + var rel = event.relatedTarget; + var cur = event.currentTarget; + if(rel && rel.nodeType == Node.TEXT_NODE) + rel = rel.parentNode; + if(rel && rel != cur && !rel.descendantOf(cur)) + return proceed(event); + }); + } + //end extension + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var name = getDOMEventName(eventName); + + var wrapper = createWrapper(element, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, + + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return Event.extend(event); + } + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize() +}); + +//mouse:wheel +(function(){ + function wheel(event){ + var delta; + // normalize the delta + if(event.wheelDelta) // IE & Opera + delta = event.wheelDelta / 120; + else if (event.detail) // W3C + delta =- event.detail / 3; + if(!delta) + return; + var custom_event = Event.element(event).fire('mouse:wheel',{ + delta: delta + }); + if(custom_event.stopped){ + Event.stop(event); + return false; + } + } + document.observe('mousewheel',wheel); + document.observe('DOMMouseScroll',wheel); +})(); + +/* End Core Extensions */ + +//from PrototypeUI +var IframeShim = Class.create({ + initialize: function() { + this.element = new Element('iframe',{ + style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none', + src: 'javascript:void(0);', + frameborder: 0 + }); + $(document.body).insert(this.element); + }, + hide: function() { + this.element.hide(); + return this; + }, + show: function() { + this.element.show(); + return this; + }, + positionUnder: function(element) { + var element = $(element); + var offset = element.cumulativeOffset(); + var dimensions = element.getDimensions(); + this.element.setStyle({ + left: offset[0] + 'px', + top: offset[1] + 'px', + width: dimensions.width + 'px', + height: dimensions.height + 'px', + zIndex: element.getStyle('zIndex') - 1 + }).show(); + return this; + }, + setBounds: function(bounds) { + for(prop in bounds) + bounds[prop] += 'px'; + this.element.setStyle(bounds); + return this; + }, + destroy: function() { + if(this.element) + this.element.remove(); + return this; + } +}); + +/** + * @author Ryan Johnson + * @copyright 2008 PersonalGrid Corporation + * @package LivePipe UI + * @license MIT + * @url http://livepipe.net/control/tabs + * @require prototype.js, livepipe.js + */ + +/*global window, document, Prototype, $, $A, $H, $break, Class, Element, Event, Control */ + +if(typeof(Prototype) == "undefined") { + throw "Control.Tabs requires Prototype to be loaded."; } +if(typeof(Object.Event) == "undefined") { + throw "Control.Tabs requires Object.Event to be loaded."; } + +Control.Tabs = Class.create({ + initialize: function(tab_list_container,options){ + if(!$(tab_list_container)) { + throw "Control.Tabs could not find the element: " + tab_list_container; } + this.activeContainer = false; + this.activeLink = false; + this.containers = $H({}); + this.links = []; + Control.Tabs.instances.push(this); + this.options = { + beforeChange: Prototype.emptyFunction, + afterChange: Prototype.emptyFunction, + hover: false, + linkSelector: 'li a', + setClassOnContainer: false, + activeClassName: 'active', + defaultTab: 'first', + autoLinkExternal: true, + targetRegExp: /#(.+)$/, + showFunction: Element.show, + hideFunction: Element.hide + }; + Object.extend(this.options,options || {}); + (typeof(this.options.linkSelector == 'string') ? + $(tab_list_container).select(this.options.linkSelector) : + this.options.linkSelector($(tab_list_container)) + ).findAll(function(link){ + return (/^#/).exec((Prototype.Browser.WebKit ? decodeURIComponent(link.href) : link.href).replace(window.location.href.split('#')[0],'')); + }).each(function(link){ + this.addTab(link); + }.bind(this)); + this.containers.values().each(Element.hide); + if(this.options.defaultTab == 'first') { + this.setActiveTab(this.links.first()); + } else if(this.options.defaultTab == 'last') { + this.setActiveTab(this.links.last()); + } else { + this.setActiveTab(this.options.defaultTab); } + var targets = this.options.targetRegExp.exec(window.location); + if(targets && targets[1]){ + targets[1].split(',').each(function(target){ + this.setActiveTab(this.links.find(function(link){ + return link.key == target; + })); + }.bind(this)); + } + if(this.options.autoLinkExternal){ + $A(document.getElementsByTagName('a')).each(function(a){ + if(!this.links.include(a)){ + var clean_href = a.href.replace(window.location.href.split('#')[0],''); + if(clean_href.substring(0,1) == '#'){ + if(this.containers.keys().include(clean_href.substring(1))){ + $(a).observe('click',function(event,clean_href){ + this.setActiveTab(clean_href.substring(1)); + }.bindAsEventListener(this,clean_href)); + } + } + } + }.bind(this)); + } + }, + addTab: function(link){ + this.links.push(link); + link.key = link.getAttribute('href').replace(window.location.href.split('#')[0],'').split('#').last().replace(/#/,''); + var container = $(link.key); + if(!container) { + throw "Control.Tabs: #" + link.key + " was not found on the page."; } + this.containers.set(link.key,container); + link[this.options.hover ? 'onmouseover' : 'onclick'] = function(link){ + if(window.event) { + Event.stop(window.event); } + this.setActiveTab(link); + return false; + }.bind(this,link); + }, + setActiveTab: function(link){ + if(!link && typeof(link) == 'undefined') { + return; } + if(typeof(link) == 'string'){ + this.setActiveTab(this.links.find(function(_link){ + return _link.key == link; + })); + }else if(typeof(link) == 'number'){ + this.setActiveTab(this.links[link]); + }else{ + if(this.notify('beforeChange',this.activeContainer,this.containers.get(link.key)) === false) { + return; } + if(this.activeContainer) { + this.options.hideFunction(this.activeContainer); } + this.links.each(function(item){ + (this.options.setClassOnContainer ? $(item.parentNode) : item).removeClassName(this.options.activeClassName); + }.bind(this)); + (this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.activeClassName); + this.activeContainer = this.containers.get(link.key); + this.activeLink = link; + this.options.showFunction(this.containers.get(link.key)); + this.notify('afterChange',this.containers.get(link.key)); + } + }, + next: function(){ + this.links.each(function(link,i){ + if(this.activeLink == link && this.links[i + 1]){ + this.setActiveTab(this.links[i + 1]); + throw $break; + } + }.bind(this)); + }, + previous: function(){ + this.links.each(function(link,i){ + if(this.activeLink == link && this.links[i - 1]){ + this.setActiveTab(this.links[i - 1]); + throw $break; + } + }.bind(this)); + }, + first: function(){ + this.setActiveTab(this.links.first()); + }, + last: function(){ + this.setActiveTab(this.links.last()); + } +}); +Object.extend(Control.Tabs,{ + instances: [], + findByTabId: function(id){ + return Control.Tabs.instances.find(function(tab){ + return tab.links.find(function(link){ + return link.key == id; + }); + }); + } +}); +Object.Event.extend(Control.Tabs); diff --git a/doc/1.6.1/language/array/from/index.html b/doc/1.6.1/language/array/from/index.html new file mode 100644 index 000000000..37cd76e6d --- /dev/null +++ b/doc/1.6.1/language/array/from/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array.from + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Array.from +

    + + + + +
    +
    +
    +
    +
    +
    Array.from(iterable) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/index.html b/doc/1.6.1/language/array/index.html new file mode 100644 index 000000000..ec00c45af --- /dev/null +++ b/doc/1.6.1/language/array/index.html @@ -0,0 +1,289 @@ + + + + + Prototype v1.6.1 API documentation | Array + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Array +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Prototype extends all native JavaScript arrays with quite a few powerful +methods.

    + +

    This is done in two ways:

    + +
      +
    • It mixes in the Enumerable module, which brings a ton of methods in +already.
    • +
    • It adds quite a few extra methods, which are documented in this section.
    • +
    + +

    With Prototype, arrays become much, much more than the trivial objects we +used to manipulate, limiting ourselves to using their length property and +their [] indexing operator. They become very powerful objects that +greatly simplify the code for 99% of the common use cases involving them.

    + +

    Why you should stop using for...in to iterate

    + +

    Many JavaScript authors have been misled into using the for...in JavaScript +construct to loop over array elements. This kind of code just won't work +with Prototype.

    + +

    The ECMA 262 standard, which defines ECMAScript 3rd edition, supposedly +implemented by all major browsers including MSIE, defines ten methods +on Array (§15.4.4), including nice methods like concat, join, pop, and +push.

    + +

    This same standard explicitly defines that the for...in construct (§12.6.4) +exists to enumerate the properties of the object appearing on the right side +of the in keyword. Only properties specifically marked as non-enumerable +are ignored by such a loop. By default, the prototype and length +properties are so marked, which prevents you from enumerating over array +methods when using for...in. This comfort led developers to use for...in as a +shortcut for indexing loops, when it is not its actual purpose.

    + +

    However, Prototype has no way to mark the methods it adds to +Array.prototype as non-enumerable. Therefore, using for...in on arrays +when using Prototype will enumerate all extended methods as well, such as +those coming from the Enumerable module, and those Prototype puts in the +Array namespace (listed further below).

    + +

    What you should use instead

    + +

    You can revert to vanilla loops:

    + +
    for (var index = 0; index < myArray.length; ++index) {
    +  var item = myArray[index];
    +  // Your code working on item here...
    +}
    +
    +
    + +

    Or you can use iterators, such as Array#each:

    + +
    myArray.each(function(item) {
    +  // Your code working on item here...
    +});
    +
    +
    + +

    The inability to use for...in on arrays is not much of a burden: as you'll +see, most of what you used to loop over arrays for can be concisely done +using the new methods provided by Array or the mixed-in Enumerable +module. So manual loops should be fairly rare.

    + +

    A note on performance

    + +

    Should you have a very large array, using iterators with lexical closures +(anonymous functions that you pass to the iterators and that get invoked at +every loop iteration) in methods like Array#each — _or_ relying on +repetitive array construction (such as uniq), may yield unsatisfactory +performance. In such cases, you're better off writing manual indexing loops, +but take care then to cache the length property and use the prefix ++ +operator:

    + +
    // Custom loop with cached length property: maximum full-loop
    +// performance on very large arrays!
    +for (var index = 0, len = myArray.length; index < len; ++index) {
    +  var item = myArray[index];
    +  // Your code working on item here...
    +}
    +
    +
    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/clear/index.html b/doc/1.6.1/language/array/prototype/clear/index.html new file mode 100644 index 000000000..4eee2b0be --- /dev/null +++ b/doc/1.6.1/language/array/prototype/clear/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array#clear + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#clear +

    + + + + +
    +
    +
    +
    +
    +
    Array#clear() → Array
    + + +

    Empties an array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/clone/index.html b/doc/1.6.1/language/array/prototype/clone/index.html new file mode 100644 index 000000000..3c3ea532b --- /dev/null +++ b/doc/1.6.1/language/array/prototype/clone/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array#clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#clone +

    + + + + +
    +
    +
    +
    +
    +
    Array#clone() → Array
    + + +

    Returns a duplicate of the array, leaving the original array intact.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/compact/index.html b/doc/1.6.1/language/array/prototype/compact/index.html new file mode 100644 index 000000000..b2bc283f4 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/compact/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array#compact + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#compact +

    + + + + +
    +
    +
    +
    +
    +
    Array#compact() → Array
    + + +

    Returns a copy of the array without any null or undefined values.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/first/index.html b/doc/1.6.1/language/array/prototype/first/index.html new file mode 100644 index 000000000..df1029729 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/first/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array#first + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#first +

    + + + + +
    +
    +
    +
    +
    +
    Array#first() → ?
    + + +

    Returns the array's first item.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/flatten/index.html b/doc/1.6.1/language/array/prototype/flatten/index.html new file mode 100644 index 000000000..9212e27ff --- /dev/null +++ b/doc/1.6.1/language/array/prototype/flatten/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.6.1 API documentation | Array#flatten + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#flatten +

    + + + + +
    +
    +
    +
    +
    +
    Array#flatten() → Array
    + + +

    Returns a "flat" (one-dimensional) version of the array.

    + +

    Nested arrays are recursively injected "inline." This can prove very +useful when handling the results of a recursive collection algorithm, +for instance.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/indexof/index.html b/doc/1.6.1/language/array/prototype/indexof/index.html new file mode 100644 index 000000000..41ec76c7b --- /dev/null +++ b/doc/1.6.1/language/array/prototype/indexof/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Array#indexOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#indexOf +

    + + + + +
    +
    +
    +
    +
    +
    Array#indexOf(item[, offset = 0]) → Number
    +
      +
    • + item + (?) + – A value that may or may not be in the array. +
    • +
    • + offset + (Number) + – The number of initial items to skip before beginning the search. +
    • +
    + + +

    Returns the position of the first occurrence of item within the array — or +-1 if item doesn't exist in the array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/inspect/index.html b/doc/1.6.1/language/array/prototype/inspect/index.html new file mode 100644 index 000000000..2be9d3848 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/inspect/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Array#inspect() → String
    + + +

    Returns the debug-oriented string representation of an array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/intersect/index.html b/doc/1.6.1/language/array/prototype/intersect/index.html new file mode 100644 index 000000000..e822f9e35 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/intersect/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.6.1 API documentation | Array#intersect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#intersect +

    + + + + +
    +
    +
    +
    +
    +
    Array#intersect(array) → Array
    +
      +
    • + array + (Array) + – A collection of values. +
    • +
    + + +

    Returns an array containing every item that is shared between the two +given arrays.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/last/index.html b/doc/1.6.1/language/array/prototype/last/index.html new file mode 100644 index 000000000..bda806d78 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/last/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array#last + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#last +

    + + + + +
    +
    +
    +
    +
    +
    Array#last() → ?
    + + +

    Returns the array's last item.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/lastindexof/index.html b/doc/1.6.1/language/array/prototype/lastindexof/index.html new file mode 100644 index 000000000..a8ea3146d --- /dev/null +++ b/doc/1.6.1/language/array/prototype/lastindexof/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Array#lastIndexOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#lastIndexOf +

    + + + + +
    +
    +
    +
    +
    +
    Array#lastIndexOf(item[, offset]) → Number
    +
      +
    • + item + (?) + – A value that may or may not be in the array. +
    • +
    • + offset + (Number) + – The number of items at the end to skip before beginning the search. +
    • +
    + + +

    Returns the position of the last occurrence of item within the array — or +-1 if item doesn't exist in the array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/reverse/index.html b/doc/1.6.1/language/array/prototype/reverse/index.html new file mode 100644 index 000000000..4824ef7e3 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/reverse/index.html @@ -0,0 +1,157 @@ + + + + + Prototype v1.6.1 API documentation | Array#reverse + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#reverse +

    + + + + +
    +
    +
    +
    +
    +
    Array#reverse([inline = false]) → Array
    +
      +
    • + inline + (Boolean) + – Whether to modify the array in place. If false, clones the original array first. +
    • +
    + + +

    Returns the reversed version of the array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/size/index.html b/doc/1.6.1/language/array/prototype/size/index.html new file mode 100644 index 000000000..495df61c4 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/size/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.6.1 API documentation | Array#size + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#size +

    + + + + +
    +
    +
    +
    +
    +
    Array#size() → Number
    + + +

    Returns the size of the array.

    + +

    This is just a local optimization of the mixed-in Enumerable#size +which avoids array cloning and uses the array's native length property.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/toarray/index.html b/doc/1.6.1/language/array/prototype/toarray/index.html new file mode 100644 index 000000000..6883005ce --- /dev/null +++ b/doc/1.6.1/language/array/prototype/toarray/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#toArray +

    + + + + +
    +
    +
    +
    +
    +
    Array#toArray() → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/tojson/index.html b/doc/1.6.1/language/array/prototype/tojson/index.html new file mode 100644 index 000000000..74482c4a1 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/tojson/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Array#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Array#toJSON() → String
    + + +

    Returns a JSON string representation of the array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/uniq/index.html b/doc/1.6.1/language/array/prototype/uniq/index.html new file mode 100644 index 000000000..e8318c423 --- /dev/null +++ b/doc/1.6.1/language/array/prototype/uniq/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.6.1 API documentation | Array#uniq + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#uniq +

    + + + + +
    +
    +
    +
    +
    +
    Array#uniq([sorted = false]) → Array
    +
      +
    • + sorted + (Boolean) + – Whether the array has already been sorted. If true, a less-costly algorithm will be used. +
    • +
    + + +

    Produces a duplicate-free version of an array. If no duplicates are +found, the original array is returned.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/array/prototype/without/index.html b/doc/1.6.1/language/array/prototype/without/index.html new file mode 100644 index 000000000..da6ab795e --- /dev/null +++ b/doc/1.6.1/language/array/prototype/without/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.6.1 API documentation | Array#without + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#without +

    + + + + +
    +
    +
    +
    +
    +
    Array#without(value...) → Array
    +
      +
    • + value + (?) + – A value to exclude. +
    • +
    + + +

    Produces a new version of the array that does not contain any of the +specified values.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/class/create/index.html b/doc/1.6.1/language/class/create/index.html new file mode 100644 index 000000000..fb19e4c99 --- /dev/null +++ b/doc/1.6.1/language/class/create/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Class.create + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Class.create +

    + + + + +
    +
    +
    +
    +
    +
    Class.create([superclass][, methods...]) → Class
    +
      +
    • + superclass + (Class) + – The optional superclass to inherit methods from. +
    • +
    • + methods + (Object) + – An object whose properties will be "mixed-in" to the new class. Any number of mixins can be added; later mixins take precedence. +
    • +
    + + +

    Creates a class.

    + +

    Class.create returns a function that, when called, will fire its own +initialize method.

    + +

    Class.create accepts two kinds of arguments. If the first argument is +a Class, it's treated as the new class's superclass, and all its +methods are inherited. Otherwise, any arguments passed are treated as +objects, and their methods are copied over as instance methods of the new +class. Later arguments take precedence over earlier arguments.

    + +

    If a subclass overrides an instance method declared in a superclass, the +subclass's method can still access the original method. To do so, declare +the subclass's method as normal, but insert $super as the first +argument. This makes $super available as a method for use within the +function.

    + +

    To extend a class after it has been defined, use Class#addMethods.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/class/index.html b/doc/1.6.1/language/class/index.html new file mode 100644 index 000000000..164956c5e --- /dev/null +++ b/doc/1.6.1/language/class/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | Class + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Class +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Manages Prototype's class-based OOP system.

    + +

    Refer to Prototype's web site for a tutorial on classes and +inheritance.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/class/prototype/addmethods/index.html b/doc/1.6.1/language/class/prototype/addmethods/index.html new file mode 100644 index 000000000..86106eaf8 --- /dev/null +++ b/doc/1.6.1/language/class/prototype/addmethods/index.html @@ -0,0 +1,195 @@ + + + + + Prototype v1.6.1 API documentation | Class#addMethods + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Class#addMethods +

    + + + + +
    +
    +
    +
    +
    +
    Class#addMethods(methods) → Class
    +
      +
    • + methods + (Object) + – The methods to add to the class. +
    • +
    + + +

    Adds methods to an existing class.

    + +

    Class#addMethods is a method available on classes that have been +defined with Class.create. It can be used to add new instance methods +to that class, or overwrite existing methods, after the class has been +defined.

    + +

    New methods propagate down the inheritance chain. If the class has +subclasses, those subclasses will receive the new methods — even in the +context of $super calls. The new methods also propagate to instances of +the class and of all its subclasses, even those that have already been +instantiated.

    + +

    Examples

    + +
    var Animal = Class.create({
    +  initialize: function(name, sound) {
    +    this.name  = name;
    +    this.sound = sound;
    +  },
    +   speak: function() {
    +    alert(this.name + " says: " + this.sound + "!");
    +  }
    +});
    + // subclassing Animal
    +var Snake = Class.create(Animal, {
    +  initialize: function($super, name) {
    +    $super(name, 'hissssssssss');
    +  }
    +});
    + var ringneck = new Snake("Ringneck");
    +ringneck.speak();
    + //-> alerts "Ringneck says: hissssssss!"
    + // adding Snake#speak (with a supercall)
    +Snake.addMethods({
    +  speak: function($super) {
    +    $super();
    +    alert("You should probably run. He looks really mad.");
    +  }
    +});
    + ringneck.speak();
    +//-> alerts "Ringneck says: hissssssss!"
    +//-> alerts "You should probably run. He looks really mad."
    + // redefining Animal#speak
    +Animal.addMethods({
    +  speak: function() {
    +    alert(this.name + 'snarls: ' + this.sound + '!');
    +  }
    +});
    + ringneck.speak();
    +//-> alerts "Ringneck snarls: hissssssss!"
    +//-> alerts "You should probably run. He looks really mad."
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/date/index.html b/doc/1.6.1/language/date/index.html new file mode 100644 index 000000000..a23814bf5 --- /dev/null +++ b/doc/1.6.1/language/date/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | Date + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Date +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Date object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/date/prototype/tojson/index.html b/doc/1.6.1/language/date/prototype/tojson/index.html new file mode 100644 index 000000000..10baa730e --- /dev/null +++ b/doc/1.6.1/language/date/prototype/tojson/index.html @@ -0,0 +1,134 @@ + + + + + Prototype v1.6.1 API documentation | Date#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Date#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Date#toJSON() → String
    + + +

    Produces a string representation of the date in ISO 8601 format.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/dollara/index.html b/doc/1.6.1/language/dollara/index.html new file mode 100644 index 000000000..2c12718e3 --- /dev/null +++ b/doc/1.6.1/language/dollara/index.html @@ -0,0 +1,136 @@ + + + + + Prototype v1.6.1 API documentation | $A + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $A +

    + + + + +
    +
    +
    +
    +
    +
    $A(iterable) → Array
    + + +

    Accepts an array-like collection (anything with numeric indices) and returns +its equivalent as an actual Array object. +This method is a convenience alias of Array.from, but is the preferred way +of casting to an Array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/dollarh/index.html b/doc/1.6.1/language/dollarh/index.html new file mode 100644 index 000000000..d02778ccd --- /dev/null +++ b/doc/1.6.1/language/dollarh/index.html @@ -0,0 +1,137 @@ + + + + + Prototype v1.6.1 API documentation | $H + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $H +

    + + + + +
    +
    +
    +
    +
    +
    $H([object]) → Hash
    + + +

    Creates a Hash.

    + +

    $H is a convenience wrapper around the Hash constructor, with a safeguard +that lets you pass an existing Hash object and get it back untouched +(instead of uselessly cloning it).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/dollarr/index.html b/doc/1.6.1/language/dollarr/index.html new file mode 100644 index 000000000..b817f5a2f --- /dev/null +++ b/doc/1.6.1/language/dollarr/index.html @@ -0,0 +1,135 @@ + + + + + Prototype v1.6.1 API documentation | $R + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $R +

    + + + + +
    +
    +
    +
    +
    +
    $R(start, end[, exclusive = false]) → ObjectRange
    + + +

    Creates a new ObjectRange object. +This method is a convenience wrapper around the ObjectRange constructor, +but $R is the preferred alias.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/dollarw/index.html b/doc/1.6.1/language/dollarw/index.html new file mode 100644 index 000000000..d1af6ab2d --- /dev/null +++ b/doc/1.6.1/language/dollarw/index.html @@ -0,0 +1,142 @@ + + + + + Prototype v1.6.1 API documentation | $w + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $w +

    + + + + +
    +
    +
    +
    +
    +
    $w(string) → Array
    +
      +
    • + string + (String) + – A string with zero or more spaces. +
    • +
    + + +

    Splits a string into an array, treating all whitespace as delimiters.

    + +

    Equivalent to Ruby's %w{foo bar} or Perl's qw(foo bar).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/index.html b/doc/1.6.1/language/enumerable/index.html new file mode 100644 index 000000000..c03ff65ab --- /dev/null +++ b/doc/1.6.1/language/enumerable/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + mixin Enumerable +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Enumerable provides a large set of useful methods for enumerations — +objects that act as collections of values. It is a cornerstone of +Prototype.

    + +

    Enumerable is a mixin: a set of methods intended not for standaone +use, but for incorporation into other objects.

    + +

    Prototype mixes Enumerable into several classes. The most visible cases +are Array and Hash, but you'll find it in less obvious spots as +well, such as in ObjectRange and various DOM- or Ajax-related objects.

    + +

    The context parameter

    + +

    Every method of Enumerable that takes an iterator also takes the "context +object" as the next (optional) parameter. The context object is what the +iterator will be bound to — what the keyword this will refer to inside +the iterator.

    + +
    var myObject = {};
    + ['foo', 'bar', 'baz'].each(function(name, index) {
    +  this[name] = index;
    +}, myObject); // we have specified the context
    + myObject
    +//-> { foo: 0, bar: 1, baz: 2}
    +
    +
    + +

    If there is no context argument, the iterator function will execute in +the scope from which the Enumerable method itself was called.

    + +

    Mixing Enumerable into your own objects

    + +

    So, let's say you've created your very own collection-like object (say, +some sort of Set, or perhaps something that dynamically fetches data +ranges from the server side, lazy-loading style). You want to be able to +mix Enumerable in (and we commend you for it). How do you go about this?

    + +

    The Enumerable module basically makes only one requirement on your object: +it must provide a method named _each (note the leading underscore) that +will accept a function as its unique argument, and will contain the actual +"raw iteration" algorithm, invoking its argument with each element in turn.

    + +

    As detailed in the documentation for Enumerable#each, Enumerable +provides all the extra layers (handling iteration short-circuits, passing +numeric indices, etc.). You just need to implement the actual iteration, +as fits your internal structure.

    + +

    If you're still confused, just have a look at the Prototype source code for +Array, Hash, or ObjectRange. They all begin with their own +_each method, which should help you grasp the idea.

    + +

    Once you're done with this, you just need to mix Enumerable in, which +you'll usually do before defining your methods, so as to make sure whatever +overrides you provide for Enumerable methods will indeed prevail. In +short, your code will probably end up looking like this:

    + +
     var YourObject = Class.create(Enumerable, {
    +  initialize: function() { // with whatever constructor arguments you need
    +    // Your construction code
    +  },
    +   _each: function(iterator) {
    +    // Your iteration code, invoking iterator at every turn
    +  },
    +   // Your other methods here, including Enumerable overrides
    +});
    +
    +
    + +

    Then, obviously, your object can be used like this:

    + +
    var obj = new YourObject();
    +// Populate the collection somehow
    +obj.pluck('somePropName');
    +obj.invoke('someMethodName');
    +obj.size();
    +// etc.
    +
    +
    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/all/index.html b/doc/1.6.1/language/enumerable/prototype/all/index.html new file mode 100644 index 000000000..dab0cfb25 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/all/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#all + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#all +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#all([iterator = Prototype.K[, context]]) → Boolean
    + + +

    Determines whether all the elements are boolean-equivalent to true, +either directly or through computation by the provided iterator.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/any/index.html b/doc/1.6.1/language/enumerable/prototype/any/index.html new file mode 100644 index 000000000..31bf67bc0 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/any/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#any + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#any +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#any([iterator = Prototype.K[, context]]) → Boolean
    + + +

    Determines whether at least one element is boolean-equivalent to true, +either directly or through computation by the provided iterator.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/collect/index.html b/doc/1.6.1/language/enumerable/prototype/collect/index.html new file mode 100644 index 000000000..e314fed04 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/collect/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#collect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#collect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#collect([iterator = Prototype.K[, context]]) → Array
    + + +

    Returns the results of applying the iterator to each element. +Aliased as Enumerable#map.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/detect/index.html b/doc/1.6.1/language/enumerable/prototype/detect/index.html new file mode 100644 index 000000000..01d7a554c --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/detect/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#detect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#detect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#detect(iterator[, context]) → firstElement | undefined
    + + +

    Finds the first element for which the iterator returns a "truthy" value. +Aliased by the Enumerable#find method.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/each/index.html b/doc/1.6.1/language/enumerable/prototype/each/index.html new file mode 100644 index 000000000..f878a7cd5 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/each/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#each + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#each +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#each(iterator[, context]) → Enumerable
    +
      +
    • + iterator + (Function) + – A Function that expects an item in the collection as the first argument and a numerical index as the second. +
    • +
    • + context + (Object) + – The scope in which to call iterator. Affects what the keyword this means inside iterator. +
    • +
    + + +

    Calls iterator for each item in the collection.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/eachslice/index.html b/doc/1.6.1/language/enumerable/prototype/eachslice/index.html new file mode 100644 index 000000000..c600aa80a --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/eachslice/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#eachSlice + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#eachSlice +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#eachSlice(number[, iterator = Prototype.K[, context]]) → Enumerable
    + + +

    Groups items into chunks of the given size. +The final "slice" may have fewer than number items; it won't "pad" the +last group with empty values. For that behavior, use +Enumerable#inGroupsOf.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/entries/index.html b/doc/1.6.1/language/enumerable/prototype/entries/index.html new file mode 100644 index 000000000..93b86a788 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/entries/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#entries + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#entries +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#entries() → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/every/index.html b/doc/1.6.1/language/enumerable/prototype/every/index.html new file mode 100644 index 000000000..cc1b70d24 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/every/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#every + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#every +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#every([iterator = Prototype.K[, context]]) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/filter/index.html b/doc/1.6.1/language/enumerable/prototype/filter/index.html new file mode 100644 index 000000000..64a473ed8 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/filter/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#filter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#filter +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#filter(iterator[, context]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/find/index.html b/doc/1.6.1/language/enumerable/prototype/find/index.html new file mode 100644 index 000000000..396aa5bf1 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/find/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#find + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#find +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#find(iterator[, context]) → firstElement | undefined
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/findall/index.html b/doc/1.6.1/language/enumerable/prototype/findall/index.html new file mode 100644 index 000000000..141bcef23 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/findall/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#findAll + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#findAll +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#findAll(iterator[, context]) → Array
    + + +

    Returns all the elements for which the iterator returned "truthy" value. +Aliased as Enumerable#select.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/grep/index.html b/doc/1.6.1/language/enumerable/prototype/grep/index.html new file mode 100644 index 000000000..f15f52b2b --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/grep/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#grep + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#grep +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#grep(regex[, iterator = Prototype.K[, context]]) → Array
    + + +

    Returns all the elements that match the filter. If an iterator is provided, +it is used to produce the returned value for each selected element.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/include/index.html b/doc/1.6.1/language/enumerable/prototype/include/index.html new file mode 100644 index 000000000..c1e0254a1 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/include/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#include +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#include(object) → Boolean
    + + +

    Determines whether a given object is in the Enumerable or not, +based on the == comparison operator. Aliased as Enumerable#member.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/ingroupsof/index.html b/doc/1.6.1/language/enumerable/prototype/ingroupsof/index.html new file mode 100644 index 000000000..827bf61a9 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/ingroupsof/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#inGroupsOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inGroupsOf +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inGroupsOf(size[, filler = null]) → [group…]
    + + +

    Groups items in fixed-size chunks, using a specific value to fill up +the last chunk if necessary.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/inject/index.html b/doc/1.6.1/language/enumerable/prototype/inject/index.html new file mode 100644 index 000000000..13af353fe --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/inject/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#inject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inject +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inject(accumulator, iterator[, context]) → accumulatedValue
    + + +

    Incrementally builds a result value based on the successive results +of the iterator. +This can be used for array construction, numerical sums/averages, etc.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/inspect/index.html b/doc/1.6.1/language/enumerable/prototype/inspect/index.html new file mode 100644 index 000000000..f301157e4 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/inspect/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inspect() → String
    + + +

    Returns the debug-oriented string representation of the object.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/invoke/index.html b/doc/1.6.1/language/enumerable/prototype/invoke/index.html new file mode 100644 index 000000000..d50ecf251 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/invoke/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#invoke + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#invoke +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#invoke(methodName[, arg...]) → Array
    + + +

    Invokes the same method, with the same arguments, for all items in a collection. +Returns the results of the method calls.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/map/index.html b/doc/1.6.1/language/enumerable/prototype/map/index.html new file mode 100644 index 000000000..c3e16e943 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/map/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#map + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#map +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#map([iterator = Prototype.K[, context]]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/max/index.html b/doc/1.6.1/language/enumerable/prototype/max/index.html new file mode 100644 index 000000000..2ca3b099a --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/max/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#max + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#max +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#max([iterator = Prototype.K[, context]]) → maxValue
    + + +

    Returns the maximum element (or element-based computation), or undefined if +the enumeration is empty. +Elements are either compared directly, or by first applying the iterator +and comparing returned values.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/member/index.html b/doc/1.6.1/language/enumerable/prototype/member/index.html new file mode 100644 index 000000000..d8abba1fd --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/member/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#member + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#member +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#member(object) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/min/index.html b/doc/1.6.1/language/enumerable/prototype/min/index.html new file mode 100644 index 000000000..73385a7a8 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/min/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#min + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#min +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#min([iterator = Prototype.K[, context]]) → minValue
    + + +

    Returns the minimum element (or element-based computation), or undefined if +the enumeration is empty. +Elements are either compared directly, or by first applying the iterator +and comparing returned values.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/partition/index.html b/doc/1.6.1/language/enumerable/prototype/partition/index.html new file mode 100644 index 000000000..3cf1211b1 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/partition/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#partition + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#partition +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#partition([iterator = Prototype.K[, context]]) → [TrueArray, FalseArray]
    + + +

    Partitions the elements in two groups: those regarded as true, and those +considered false. +By default, regular JavaScript boolean equivalence is used, but an iterator +can be provided, that computes a boolean representation of the elements.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/pluck/index.html b/doc/1.6.1/language/enumerable/prototype/pluck/index.html new file mode 100644 index 000000000..f205193ff --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/pluck/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#pluck + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#pluck +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#pluck(propertyName) → Array
    + + +

    Optimization for a common use-case of collect: fetching the same property +for all the elements. Returns the property values.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/reject/index.html b/doc/1.6.1/language/enumerable/prototype/reject/index.html new file mode 100644 index 000000000..438f17af3 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/reject/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#reject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#reject +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#reject(iterator[, context]) → Array
    + + +

    Returns all the elements for which the iterator returned a "falsy" value.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/select/index.html b/doc/1.6.1/language/enumerable/prototype/select/index.html new file mode 100644 index 000000000..b82d0cdd1 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/select/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#select +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#select(iterator[, context]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/size/index.html b/doc/1.6.1/language/enumerable/prototype/size/index.html new file mode 100644 index 000000000..d3f78ea1d --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/size/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#size + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#size +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#size() → Number
    + + +

    Returns the size of the enumeration.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/some/index.html b/doc/1.6.1/language/enumerable/prototype/some/index.html new file mode 100644 index 000000000..2c611dbe7 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/some/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#some + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#some +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#some([iterator = Prototype.K[, context]]) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/sortby/index.html b/doc/1.6.1/language/enumerable/prototype/sortby/index.html new file mode 100644 index 000000000..84686f0d8 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/sortby/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#sortBy + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#sortBy +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#sortBy(iterator[, context]) → Array
    + + +

    Provides a custom-sorted view of the elements based on the criteria computed, +for each element, by the iterator.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/toarray/index.html b/doc/1.6.1/language/enumerable/prototype/toarray/index.html new file mode 100644 index 000000000..59ba18c53 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/toarray/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#toArray +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#toArray() → Array
    + + +

    Returns an Array representation of the enumeration.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/enumerable/prototype/zip/index.html b/doc/1.6.1/language/enumerable/prototype/zip/index.html new file mode 100644 index 000000000..213af62d8 --- /dev/null +++ b/doc/1.6.1/language/enumerable/prototype/zip/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | Enumerable#zip + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#zip +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#zip(sequence...[, iterator = Prototype.K]) → Array
    + + +

    Zips together (think of the zip on a pair of trousers) 2+ sequences, +providing an array of tuples. +Each tuple contains one value per original sequence. +Tuples can be converted to something else by applying the optional iterator on them.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/index.html b/doc/1.6.1/language/function/index.html new file mode 100644 index 000000000..6ebc86c31 --- /dev/null +++ b/doc/1.6.1/language/function/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.6.1 API documentation | Function + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Function +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Function object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/prototype/argumentnames/index.html b/doc/1.6.1/language/function/prototype/argumentnames/index.html new file mode 100644 index 000000000..22c77b3d9 --- /dev/null +++ b/doc/1.6.1/language/function/prototype/argumentnames/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.6.1 API documentation | Function#argumentNames + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#argumentNames +

    + + + + +
    +
    +
    +
    +
    +
    Function#argumentNames() → Array
    + + +

    Reads the argument names as stated in the function definition and returns +the values as an array of strings (or an empty array if the function is +defined without parameters).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/prototype/bind/index.html b/doc/1.6.1/language/function/prototype/bind/index.html new file mode 100644 index 000000000..0a23a021f --- /dev/null +++ b/doc/1.6.1/language/function/prototype/bind/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.6.1 API documentation | Function#bind + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#bind +

    + + + + +
    +
    +
    +
    +
    +
    Function#bind(object[, args...]) → Function
    +
      +
    • + object + (Object) + – The object to bind to. +
    • +
    + + +

    Wraps the function in another, locking its execution scope to an object +specified by object.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/prototype/bindaseventlistener/index.html b/doc/1.6.1/language/function/prototype/bindaseventlistener/index.html new file mode 100644 index 000000000..36d7c3fdd --- /dev/null +++ b/doc/1.6.1/language/function/prototype/bindaseventlistener/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.6.1 API documentation | Function#bindAsEventListener + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#bindAsEventListener +

    + + + + +
    +
    +
    +
    +
    +
    Function#bindAsEventListener(object[, args...]) → Function
    +
      +
    • + object + (Object) + – The object to bind to. +
    • +
    + + +

    An event-specific variant of Function#bind which ensures the function +will recieve the current event object as the first argument when +executing.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/prototype/curry/index.html b/doc/1.6.1/language/function/prototype/curry/index.html new file mode 100644 index 000000000..f78f50224 --- /dev/null +++ b/doc/1.6.1/language/function/prototype/curry/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.6.1 API documentation | Function#curry + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#curry +

    + + + + +
    +
    +
    +
    +
    +
    Function#curry(args...) → Function
    + + +

    Partially applies the function, returning a function with one or more +arguments already "filled in."

    + +

    Function#curry works just like Function#bind without the initial +scope argument. Use the latter if you need to partially apply a function +and modify its execution scope at the same time.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/prototype/defer/index.html b/doc/1.6.1/language/function/prototype/defer/index.html new file mode 100644 index 000000000..44a945551 --- /dev/null +++ b/doc/1.6.1/language/function/prototype/defer/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | Function#defer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#defer +

    + + + + +
    +
    +
    +
    +
    +
    Function#defer(args...) → Number
    + + +

    Schedules the function to run as soon as the interpreter is idle.

    + +

    A "deferred" function will not run immediately; rather, it will run as soon +as the interpreter's call stack is empty.

    + +

    Behaves much like window.setTimeout with a delay set to 0. Returns an +ID that can be used to clear the timeout with window.clearTimeout before +it runs.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/prototype/delay/index.html b/doc/1.6.1/language/function/prototype/delay/index.html new file mode 100644 index 000000000..3fe0d6284 --- /dev/null +++ b/doc/1.6.1/language/function/prototype/delay/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Function#delay + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#delay +

    + + + + +
    +
    +
    +
    +
    +
    Function#delay(seconds[, args...]) → Number
    +
      +
    • + seconds + (Number) + – How long to wait before calling the function. +
    • +
    + + +

    Schedules the function to run after the specified amount of time, passing +any arguments given.

    + +

    Behaves much like window.setTimeout. Returns an integer ID that can be +used to clear the timeout with window.clearTimeout before it runs.

    + +

    To schedule a function to run as soon as the interpreter is idle, use +Function#defer.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/prototype/methodize/index.html b/doc/1.6.1/language/function/prototype/methodize/index.html new file mode 100644 index 000000000..fde8edaeb --- /dev/null +++ b/doc/1.6.1/language/function/prototype/methodize/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.6.1 API documentation | Function#methodize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#methodize +

    + + + + +
    +
    +
    +
    +
    +
    Function#methodize() → Function
    + + +

    Wraps the function inside another function that, at call time, pushes +this to the original function as the first argument.

    + +

    Used to define both a generic method and an instance method.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/function/prototype/wrap/index.html b/doc/1.6.1/language/function/prototype/wrap/index.html new file mode 100644 index 000000000..f4ad5fb05 --- /dev/null +++ b/doc/1.6.1/language/function/prototype/wrap/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.6.1 API documentation | Function#wrap + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#wrap +

    + + + + +
    +
    +
    +
    +
    +
    Function#wrap(wrapperFunction) → Function
    +
      +
    • + wrapperFunction + (Function) + – The function to act as a wrapper. +
    • +
    + + +

    Returns a function "wrapped" around the original function.

    + +

    Function#wrap distills the essence of aspect-oriented programming into +a single method, letting you easily build on existing functions by +specifying before and after behavior, transforming the return value, or +even preventing the original function from being called.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/index.html b/doc/1.6.1/language/hash/index.html new file mode 100644 index 000000000..b87d13fd8 --- /dev/null +++ b/doc/1.6.1/language/hash/index.html @@ -0,0 +1,210 @@ + + + + + Prototype v1.6.1 API documentation | Hash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Hash +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A set of key/value pairs.

    + +

    Hash can be thought of as an associative array, binding unique keys to +values (which are not necessarily unique), though it can not guarantee +consistent order its elements when iterating. Because of the nature of +JavaScript, every object is in fact a hash; but Hash adds a number of +methods that let you enumerate keys and values, iterate over key/value +pairs, merge two hashes together, and much more.

    + +

    Creating a hash

    + +

    There are two ways to construct a Hash instance: the first is regular +JavaScript object instantiation with the new keyword, and the second is +using the $H function. There is one difference between them: if a Hash +is passed to $H, it will be returned as-is, wherease the same hash passed +to new Hash will be cloned instead.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Hash

    +
    +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/new/index.html b/doc/1.6.1/language/hash/new/index.html new file mode 100644 index 000000000..6fa87bf64 --- /dev/null +++ b/doc/1.6.1/language/hash/new/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | new Hash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Hash +

    + + + + +
    +
    +
    +
    +
    +
    new([object])
    + + +

    Creates a new Hash. If object is given, the new hash will be populated +with all the object's properties. See $H.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/clone/index.html b/doc/1.6.1/language/hash/prototype/clone/index.html new file mode 100644 index 000000000..fa436a23d --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/clone/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#clone +

    + + + + +
    +
    +
    +
    +
    +
    Hash#clone() → Hash
    + + +

    Returns a clone of hash.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/get/index.html b/doc/1.6.1/language/hash/prototype/get/index.html new file mode 100644 index 000000000..a4d4d4dbb --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/get/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#get + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#get +

    + + + + +
    +
    +
    +
    +
    +
    Hash#get(key) → value
    + + +

    Returns the value of the hash's key property.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/index/index.html b/doc/1.6.1/language/hash/prototype/index/index.html new file mode 100644 index 000000000..af8bd4694 --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/index/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | Hash#index + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#index +

    + + + + +
    +
    +
    +
    +
    +
    Hash#index(value) → String
    + + +

    Returns the first key in the hash whose value matches value. +Returns false if there is no such key.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/inspect/index.html b/doc/1.6.1/language/hash/prototype/inspect/index.html new file mode 100644 index 000000000..3662e3d59 --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/inspect/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Hash#inspect() → String
    + + +

    Returns the debug-oriented string representation of the hash.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/keys/index.html b/doc/1.6.1/language/hash/prototype/keys/index.html new file mode 100644 index 000000000..4375cbb4d --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/keys/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#keys + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#keys +

    + + + + +
    +
    +
    +
    +
    +
    Hash#keys() → [String…]
    + + +

    Provides an Array of keys (that is, property names) for the hash.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/merge/index.html b/doc/1.6.1/language/hash/prototype/merge/index.html new file mode 100644 index 000000000..b223bae7c --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/merge/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.6.1 API documentation | Hash#merge + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#merge +

    + + + + +
    +
    +
    +
    +
    +
    Hash#merge(object) → Hash
    + + +

    Returns a new hash with object's key/value pairs merged in. +To modify the original hash in place, use Hash#update.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/set/index.html b/doc/1.6.1/language/hash/prototype/set/index.html new file mode 100644 index 000000000..9572280d6 --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/set/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#set + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#set +

    + + + + +
    +
    +
    +
    +
    +
    Hash#set(key, value) → value
    + + +

    Sets the hash's key property to value and returns value.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/tojson/index.html b/doc/1.6.1/language/hash/prototype/tojson/index.html new file mode 100644 index 000000000..fa6a9e90b --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/tojson/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toJSON() → String
    + + +

    Returns a JSON string.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/toobject/index.html b/doc/1.6.1/language/hash/prototype/toobject/index.html new file mode 100644 index 000000000..4685379fe --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/toobject/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#toObject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toObject +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toObject() → Object
    + + +

    Returns a cloned, vanilla object.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/toquerystring/index.html b/doc/1.6.1/language/hash/prototype/toquerystring/index.html new file mode 100644 index 000000000..006080037 --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/toquerystring/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#toQueryString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toQueryString +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toQueryString() → String
    + + +

    Turns a hash into its URL-encoded query string representation.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/unset/index.html b/doc/1.6.1/language/hash/prototype/unset/index.html new file mode 100644 index 000000000..a26ccf9b2 --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/unset/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#unset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#unset +

    + + + + +
    +
    +
    +
    +
    +
    Hash#unset(key) → value
    + + +

    Deletes the hash's key property and returns its value.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/update/index.html b/doc/1.6.1/language/hash/prototype/update/index.html new file mode 100644 index 000000000..cfb4d458c --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/update/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.6.1 API documentation | Hash#update + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#update +

    + + + + +
    +
    +
    +
    +
    +
    Hash#update(object) → Hash
    + + +

    Updates hash with the key/value pairs of object. +The original hash will be modified. To return a new hash instead, use +Hash#merge.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/hash/prototype/values/index.html b/doc/1.6.1/language/hash/prototype/values/index.html new file mode 100644 index 000000000..a7e31edde --- /dev/null +++ b/doc/1.6.1/language/hash/prototype/values/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | Hash#values + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#values +

    + + + + +
    +
    +
    +
    +
    +
    Hash#values() → Array
    + + +

    Collect the values of a hash and returns them in an array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/index.html b/doc/1.6.1/language/index.html new file mode 100644 index 000000000..8719c9463 --- /dev/null +++ b/doc/1.6.1/language/index.html @@ -0,0 +1,216 @@ + + + + + Prototype v1.6.1 API documentation | Language section + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +

    + section Language section +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Additions to JavaScript's "standard library" and extensions to +built-in JavaScript objects.

    +
    +
    + + + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Class

      + +

      Manages Prototype's class-based OOP system.

      +
    • +
    • +

      Try

      + +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Array

      + +

      Prototype extends all native JavaScript arrays with quite a few powerful +methods.

      +
    • +
    • +

      Date

      + +

      Extensions to the built-in Date object.

      +
    • +
    • +

      Function

      + +

      Extensions to the built-in Function object.

      +
    • +
    • +

      Hash

      + +

      A set of key/value pairs.

      +
    • +
    • +

      Number

      + +

      Extensions to the built-in Number object.

      +
    • +
    • +

      Object

      + +

      Extensions to the built-in Object object.

      +
    • +
    • +

      ObjectRange

      + +

      A succession of values.

      +
    • +
    • +

      PeriodicalExecuter

      + +

      A class that oversees the calling of a particular function periodically.

      +
    • +
    • +

      RegExp

      + +

      Extensions to the built-in RegExp object.

      +
    • +
    • +

      String

      + +

      Extensions to the built-in String class.

      +
    • +
    • +

      Template

      + +

      A class for sophisticated string interpolation.

      +
    • +
    +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/index.html b/doc/1.6.1/language/number/index.html new file mode 100644 index 000000000..f127b87be --- /dev/null +++ b/doc/1.6.1/language/number/index.html @@ -0,0 +1,182 @@ + + + + + Prototype v1.6.1 API documentation | Number + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Number +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Number object.

    + +

    Prototype extends native JavaScript numbers in order to provide:

    + + +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/abs/index.html b/doc/1.6.1/language/number/prototype/abs/index.html new file mode 100644 index 000000000..618e807a8 --- /dev/null +++ b/doc/1.6.1/language/number/prototype/abs/index.html @@ -0,0 +1,142 @@ + + + + + Prototype v1.6.1 API documentation | Number#abs + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#abs +

    + + + + +
    +
    +
    +
    +
    +
    Number#abs() → Number
    + + +

    Returns the absolute value of the number.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/ceil/index.html b/doc/1.6.1/language/number/prototype/ceil/index.html new file mode 100644 index 000000000..d2225f5cc --- /dev/null +++ b/doc/1.6.1/language/number/prototype/ceil/index.html @@ -0,0 +1,142 @@ + + + + + Prototype v1.6.1 API documentation | Number#ceil + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#ceil +

    + + + + +
    +
    +
    +
    +
    +
    Number#ceil() → Number
    + + +

    Returns the smallest integer greater than or equal to the number.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/floor/index.html b/doc/1.6.1/language/number/prototype/floor/index.html new file mode 100644 index 000000000..c5c1a3884 --- /dev/null +++ b/doc/1.6.1/language/number/prototype/floor/index.html @@ -0,0 +1,142 @@ + + + + + Prototype v1.6.1 API documentation | Number#floor + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#floor +

    + + + + +
    +
    +
    +
    +
    +
    Number#floor() → Number
    + + +

    Returns the largest integer less than or equal to the number.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/round/index.html b/doc/1.6.1/language/number/prototype/round/index.html new file mode 100644 index 000000000..226aacec8 --- /dev/null +++ b/doc/1.6.1/language/number/prototype/round/index.html @@ -0,0 +1,142 @@ + + + + + Prototype v1.6.1 API documentation | Number#round + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#round +

    + + + + +
    +
    +
    +
    +
    +
    Number#round() → Number
    + + +

    Rounds the number to the nearest integer.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/succ/index.html b/doc/1.6.1/language/number/prototype/succ/index.html new file mode 100644 index 000000000..8142abb76 --- /dev/null +++ b/doc/1.6.1/language/number/prototype/succ/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.6.1 API documentation | Number#succ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#succ +

    + + + + +
    +
    +
    +
    +
    +
    Number#succ() → Number
    + + +

    Returns the successor of the current Number, as defined by current + 1. +Used to make numbers compatible with ObjectRange.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/times/index.html b/doc/1.6.1/language/number/prototype/times/index.html new file mode 100644 index 000000000..48a378206 --- /dev/null +++ b/doc/1.6.1/language/number/prototype/times/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.6.1 API documentation | Number#times + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#times +

    + + + + +
    +
    +
    +
    +
    +
    Number#times(iterator) → Number
    + + +

    Calls iterator the specified number of times. +The function takes an integer as the first parameter; it will start at 0 +and be incremented after each invocation.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/tocolorpart/index.html b/doc/1.6.1/language/number/prototype/tocolorpart/index.html new file mode 100644 index 000000000..adfc645ad --- /dev/null +++ b/doc/1.6.1/language/number/prototype/tocolorpart/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.6.1 API documentation | Number#toColorPart + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#toColorPart +

    + + + + +
    +
    +
    +
    +
    +
    Number#toColorPart() → String
    + + +

    Produces a 2-digit hexadecimal representation of the number +(which is therefore assumed to be in the [0..255] range). +Useful for composing CSS color strings.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/tojson/index.html b/doc/1.6.1/language/number/prototype/tojson/index.html new file mode 100644 index 000000000..5abd37dd4 --- /dev/null +++ b/doc/1.6.1/language/number/prototype/tojson/index.html @@ -0,0 +1,142 @@ + + + + + Prototype v1.6.1 API documentation | Number#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Number#toJSON() → String
    + + +

    Returns a JSON string representation of the number.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/number/prototype/topaddedstring/index.html b/doc/1.6.1/language/number/prototype/topaddedstring/index.html new file mode 100644 index 000000000..707dc0d8d --- /dev/null +++ b/doc/1.6.1/language/number/prototype/topaddedstring/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.6.1 API documentation | Number#toPaddedString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#toPaddedString +

    + + + + +
    +
    +
    +
    +
    +
    Number#toPaddedString(length[, radix]) → String
    + + +

    Converts the number into a string padded with 0s so that the string's length +is at least equal to length. +Takes an optional radix argument which specifies the base to use for conversion.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/clone/index.html b/doc/1.6.1/language/object/clone/index.html new file mode 100644 index 000000000..ffbec7fa9 --- /dev/null +++ b/doc/1.6.1/language/object/clone/index.html @@ -0,0 +1,160 @@ + + + + + Prototype v1.6.1 API documentation | Object.clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.clone +

    + + + + +
    +
    +
    +
    +
    +
    Object.clone(object) → Object
    +
      +
    • + object + (Object) + – The object to clone. +
    • +
    + + +

    Duplicates the passed object.

    + +

    Copies all the original's key/value pairs onto an empty object.

    + +

    Do note that this is a shallow copy, not a deep copy. Nested objects +will retain their references.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/extend/index.html b/doc/1.6.1/language/object/extend/index.html new file mode 100644 index 000000000..836079dc8 --- /dev/null +++ b/doc/1.6.1/language/object/extend/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.6.1 API documentation | Object.extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.extend +

    + + + + +
    +
    +
    +
    +
    +
    Object.extend(destination, source) → Object
    +
      +
    • + destination + (Object) + – The object to receive the new properties. +
    • +
    • + source + (Object) + – The object whose properties will be duplicated. +
    • +
    + + +

    Copies all properties from the source to the destination object. Returns +the destination object.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/index.html b/doc/1.6.1/language/object/index.html new file mode 100644 index 000000000..bff410abb --- /dev/null +++ b/doc/1.6.1/language/object/index.html @@ -0,0 +1,194 @@ + + + + + Prototype v1.6.1 API documentation | Object + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Object +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Object object.

    + +

    Because it is dangerous and invasive to augment Object.prototype (i.e., +add instance methods to objects), all these methods are static methods that +take an Object as their first parameter.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/inspect/index.html b/doc/1.6.1/language/object/inspect/index.html new file mode 100644 index 000000000..3f4b8af5b --- /dev/null +++ b/doc/1.6.1/language/object/inspect/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | Object.inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.inspect +

    + + + + +
    +
    +
    +
    +
    +
    Object.inspect(object) → String
    +
      +
    • + object + (Object) + – The item to be inspected. +
    • +
    + + +

    Returns the debug-oriented string representation of the object.

    + +

    undefined and null are represented as such.

    + +

    Other types are checked for a inspect method. If there is one, it is +used; otherwise, it reverts to the toString method.

    + +

    Prototype provides inspect methods for many types, both built-in and +library-defined — among them String, Array, Enumerable and Hash. +These attempt to provide useful string representations (from a +developer's standpoint) for their respective types.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/isarray/index.html b/doc/1.6.1/language/object/isarray/index.html new file mode 100644 index 000000000..fd2a226bd --- /dev/null +++ b/doc/1.6.1/language/object/isarray/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Object.isArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isArray +

    + + + + +
    +
    +
    +
    +
    +
    Object.isArray(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is an array; false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/iselement/index.html b/doc/1.6.1/language/object/iselement/index.html new file mode 100644 index 000000000..31df8043d --- /dev/null +++ b/doc/1.6.1/language/object/iselement/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Object.isElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isElement +

    + + + + +
    +
    +
    +
    +
    +
    Object.isElement(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is a DOM node of type 1; false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/isfunction/index.html b/doc/1.6.1/language/object/isfunction/index.html new file mode 100644 index 000000000..6732d6679 --- /dev/null +++ b/doc/1.6.1/language/object/isfunction/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Object.isFunction + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isFunction +

    + + + + +
    +
    +
    +
    +
    +
    Object.isFunction(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type function; false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/ishash/index.html b/doc/1.6.1/language/object/ishash/index.html new file mode 100644 index 000000000..109fd906a --- /dev/null +++ b/doc/1.6.1/language/object/ishash/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.6.1 API documentation | Object.isHash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isHash +

    + + + + +
    +
    +
    +
    +
    +
    Object.isHash(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is an instance of the Hash class; false +otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/isnumber/index.html b/doc/1.6.1/language/object/isnumber/index.html new file mode 100644 index 000000000..5976c1488 --- /dev/null +++ b/doc/1.6.1/language/object/isnumber/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Object.isNumber + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isNumber +

    + + + + +
    +
    +
    +
    +
    +
    Object.isNumber(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type number; false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/isstring/index.html b/doc/1.6.1/language/object/isstring/index.html new file mode 100644 index 000000000..6d38e03f6 --- /dev/null +++ b/doc/1.6.1/language/object/isstring/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Object.isString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isString +

    + + + + +
    +
    +
    +
    +
    +
    Object.isString(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type string; false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/isundefined/index.html b/doc/1.6.1/language/object/isundefined/index.html new file mode 100644 index 000000000..912cd0eda --- /dev/null +++ b/doc/1.6.1/language/object/isundefined/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.6.1 API documentation | Object.isUndefined + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isUndefined +

    + + + + +
    +
    +
    +
    +
    +
    Object.isUndefined(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type string; false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/keys/index.html b/doc/1.6.1/language/object/keys/index.html new file mode 100644 index 000000000..8518828e3 --- /dev/null +++ b/doc/1.6.1/language/object/keys/index.html @@ -0,0 +1,160 @@ + + + + + Prototype v1.6.1 API documentation | Object.keys + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.keys +

    + + + + +
    +
    +
    +
    +
    +
    Object.keys(object) → Array
    +
      +
    • + object + (Object) + – The object to pull keys from. +
    • +
    + + +

    Returns an array of the object's property names.

    + +

    Note that the order of the resulting array is browser-dependent — it +relies on the for&#8230;in loop, for which the ECMAScript spec does not +prescribe an enumeration order. Sort the resulting array if you wish to +normalize the order of the object keys.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/tohtml/index.html b/doc/1.6.1/language/object/tohtml/index.html new file mode 100644 index 000000000..b8526b878 --- /dev/null +++ b/doc/1.6.1/language/object/tohtml/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.6.1 API documentation | Object.toHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toHTML +

    + + + + +
    +
    +
    +
    +
    +
    Object.toHTML(object) → String
    +
      +
    • + object + (Object) + – The object to convert to HTML. +
    • +
    + + +

    Converts the object to its HTML representation.

    + +

    Returns the return value of object's toHTML method if it exists; else +runs object through String.interpret.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/tojson/index.html b/doc/1.6.1/language/object/tojson/index.html new file mode 100644 index 000000000..89c7d1ad7 --- /dev/null +++ b/doc/1.6.1/language/object/tojson/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | Object.toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Object.toJSON(object) → String
    +
      +
    • + object + (Object) + – The object to be serialized. +
    • +
    + + +

    Returns a JSON string.

    + +

    undefined and function types have no JSON representation. boolean +and null are coerced to strings.

    + +

    For other types, Object.toJSON looks for a toJSON method on object. +If there is one, it is used; otherwise the object is treated like a +generic Object.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/toquerystring/index.html b/doc/1.6.1/language/object/toquerystring/index.html new file mode 100644 index 000000000..c35a86520 --- /dev/null +++ b/doc/1.6.1/language/object/toquerystring/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.6.1 API documentation | Object.toQueryString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toQueryString +

    + + + + +
    +
    +
    +
    +
    +
    Object.toQueryString(object) → String
    + + +

    object (Object): The object whose property/value pairs will be converted.

    + +

    Turns an object into its URL-encoded query string representation.

    + +

    This is a form of serialization, and is mostly useful to provide complex +parameter sets for stuff such as objects in the Ajax namespace (e.g. +Ajax.Request).

    + +

    Undefined-value pairs will be serialized as if empty-valued. Array-valued +pairs will get serialized with one name/value pair per array element. All +values get URI-encoded using JavaScript's native encodeURIComponent +function.

    + +

    The order of pairs in the serialized form is not guaranteed (and mostly +irrelevant anyway) — except for array-based parts, which are serialized +in array order.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/object/values/index.html b/doc/1.6.1/language/object/values/index.html new file mode 100644 index 000000000..d346b4c3a --- /dev/null +++ b/doc/1.6.1/language/object/values/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | Object.values + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.values +

    + + + + +
    +
    +
    +
    +
    +
    Object.values(object) → Array
    +
      +
    • + object + (Object) + – The object to pull values from. +
    • +
    + + +

    Returns an array of the object's values.

    + +

    Note that the order of the resulting array is browser-dependent — it +relies on the for&#8230;in loop, for which the ECMAScript spec does not +prescribe an enumeration order.

    + +

    Also, remember that while property names are unique, property values +have no such constraint.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/objectrange/index.html b/doc/1.6.1/language/objectrange/index.html new file mode 100644 index 000000000..911597395 --- /dev/null +++ b/doc/1.6.1/language/objectrange/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.6.1 API documentation | ObjectRange + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class ObjectRange +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A succession of values.

    + +

    An ObjectRange can model a range of any value that implements a succ +method (which links that value to its "successor").

    + +

    Prototype provides such a method for Number and String, but you +are (of course) welcome to implement useful semantics in your own objects, +in order to enable ranges based on them.

    + +

    ObjectRange mixes in Enumerable, which makes ranges very versatile. +It takes care, however, to override the default code for include, to +achieve better efficiency.

    + +

    While ObjectRange does provide a constructor, the preferred way to obtain +a range is to use the $R utility function, which is strictly equivalent +(only way more concise to use).

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/objectrange/new/index.html b/doc/1.6.1/language/objectrange/new/index.html new file mode 100644 index 000000000..b3d9f4665 --- /dev/null +++ b/doc/1.6.1/language/objectrange/new/index.html @@ -0,0 +1,138 @@ + + + + + Prototype v1.6.1 API documentation | new ObjectRange + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new ObjectRange +

    + + + + +
    +
    +
    +
    +
    +
    new(start, end[, exclusive = false])
    + + +

    Creates a new ObjectRange.

    + +

    The exclusive argument specifies whether end itself is a part of the +range.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/objectrange/prototype/include/index.html b/doc/1.6.1/language/objectrange/prototype/include/index.html new file mode 100644 index 000000000..250255d43 --- /dev/null +++ b/doc/1.6.1/language/objectrange/prototype/include/index.html @@ -0,0 +1,135 @@ + + + + + Prototype v1.6.1 API documentation | ObjectRange#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method ObjectRange#include +

    + + + + +
    +
    +
    +
    +
    +
    ObjectRange#include(value) → Boolean
    + + +

    Determines whether the value is included in the range.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/periodicalexecuter/index.html b/doc/1.6.1/language/periodicalexecuter/index.html new file mode 100644 index 000000000..7e86d809e --- /dev/null +++ b/doc/1.6.1/language/periodicalexecuter/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.6.1 API documentation | PeriodicalExecuter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class PeriodicalExecuter +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A class that oversees the calling of a particular function periodically.

    + +

    PeriodicalExecuter shields you from multiple parallel executions of the +callback function, should it take longer than the given interval to +execute.

    + +

    This is especially useful if you use one to interact with the user at +given intervals (e.g. use a prompt or confirm call): this will avoid +multiple message boxes all waiting to be actioned.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/periodicalexecuter/new/index.html b/doc/1.6.1/language/periodicalexecuter/new/index.html new file mode 100644 index 000000000..269b448af --- /dev/null +++ b/doc/1.6.1/language/periodicalexecuter/new/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.6.1 API documentation | new PeriodicalExecuter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new PeriodicalExecuter +

    + + + + +
    +
    +
    +
    +
    +
    new(callback, frequency)
    +
      +
    • + callback + (Function) + – the function to be executed at each interval. +
    • +
    • + frequency + (Number) + – the amount of time, in sections, to wait in between callbacks. +
    • +
    + + +

    Creates an PeriodicalExecuter.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/periodicalexecuter/prototype/stop/index.html b/doc/1.6.1/language/periodicalexecuter/prototype/stop/index.html new file mode 100644 index 000000000..2f82d94f3 --- /dev/null +++ b/doc/1.6.1/language/periodicalexecuter/prototype/stop/index.html @@ -0,0 +1,135 @@ + + + + + Prototype v1.6.1 API documentation | PeriodicalExecuter#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method PeriodicalExecuter#stop +

    + + + + +
    +
    +
    +
    +
    +
    PeriodicalExecuter#stop() → undefined
    + + +

    Stops the periodical executer (there will be no further triggers).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/regexp/escape/index.html b/doc/1.6.1/language/regexp/escape/index.html new file mode 100644 index 000000000..b4bf5a41a --- /dev/null +++ b/doc/1.6.1/language/regexp/escape/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.6.1 API documentation | RegExp.escape + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method RegExp.escape +

    + + + + +
    +
    +
    +
    +
    +
    RegExp.escape(str) → String
    +
      +
    • + str + (String) + – A string intended to be used in a RegExp constructor. +
    • +
    + + +

    Escapes any characters in the string that have special meaning in a +regular expression.

    + +

    Use before passing a string into the RegExp constructor.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/regexp/index.html b/doc/1.6.1/language/regexp/index.html new file mode 100644 index 000000000..b52403491 --- /dev/null +++ b/doc/1.6.1/language/regexp/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.6.1 API documentation | RegExp + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class RegExp +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in RegExp object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/regexp/prototype/match/index.html b/doc/1.6.1/language/regexp/prototype/match/index.html new file mode 100644 index 000000000..e6b030d31 --- /dev/null +++ b/doc/1.6.1/language/regexp/prototype/match/index.html @@ -0,0 +1,135 @@ + + + + + Prototype v1.6.1 API documentation | RegExp#match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method RegExp#match +

    + + + + +
    +
    +
    +
    +
    +
    RegExp#match(str) → Boolean
    + + +

    Return true if string matches the regular expression, false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/index.html b/doc/1.6.1/language/string/index.html new file mode 100644 index 000000000..e97df68aa --- /dev/null +++ b/doc/1.6.1/language/string/index.html @@ -0,0 +1,258 @@ + + + + + Prototype v1.6.1 API documentation | String + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class String +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in String class.

    + +

    Prototype enhances the String object with a series of useful methods for +ranging from the trivial to the complex. Tired of stripping trailing +whitespace? Try String#strip. Want to replace replace? Have a look at +String#sub and String#gsub. Need to parse a query string? We have +String#toQueryParams.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/interpret/index.html b/doc/1.6.1/language/string/interpret/index.html new file mode 100644 index 000000000..4d7a23898 --- /dev/null +++ b/doc/1.6.1/language/string/interpret/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String.interpret + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method String.interpret +

    + + + + +
    +
    +
    +
    +
    +
    String.interpret(value) → String
    + + +

    Coerces value into a string. Returns an empty string for null.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/blank/index.html b/doc/1.6.1/language/string/prototype/blank/index.html new file mode 100644 index 000000000..8ab5ec0bd --- /dev/null +++ b/doc/1.6.1/language/string/prototype/blank/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#blank + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#blank +

    + + + + +
    +
    +
    +
    +
    +
    String#blank() → Boolean
    + + +

    Check if the string is "blank" — either empty (length of 0) or containing +only whitespace.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/camelize/index.html b/doc/1.6.1/language/string/prototype/camelize/index.html new file mode 100644 index 000000000..abdee7244 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/camelize/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.6.1 API documentation | String#camelize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#camelize +

    + + + + +
    +
    +
    +
    +
    +
    String#camelize() → String
    + + +

    Converts a string separated by dashes into a camelCase equivalent. +For instance, 'foo-bar' would be converted to 'fooBar'.

    + +

    Examples

    + +
    'background-color'.camelize();
    +// -> 'backgroundColor'
    + '-moz-binding'.camelize();
    +// -> 'MozBinding'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/capitalize/index.html b/doc/1.6.1/language/string/prototype/capitalize/index.html new file mode 100644 index 000000000..f42b591ec --- /dev/null +++ b/doc/1.6.1/language/string/prototype/capitalize/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#capitalize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#capitalize +

    + + + + +
    +
    +
    +
    +
    +
    String#capitalize() → String
    + + +

    Capitalizes the first letter of a string and downcases all the others.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/dasherize/index.html b/doc/1.6.1/language/string/prototype/dasherize/index.html new file mode 100644 index 000000000..67321425c --- /dev/null +++ b/doc/1.6.1/language/string/prototype/dasherize/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#dasherize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#dasherize +

    + + + + +
    +
    +
    +
    +
    +
    String#dasherize() → String
    + + +

    Replaces every instance of the underscore character ("_") by a dash ("-").

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/empty/index.html b/doc/1.6.1/language/string/prototype/empty/index.html new file mode 100644 index 000000000..019cc23f6 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/empty/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#empty + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#empty +

    + + + + +
    +
    +
    +
    +
    +
    String#empty() → Boolean
    + + +

    Checks if the string is empty.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/endswith/index.html b/doc/1.6.1/language/string/prototype/endswith/index.html new file mode 100644 index 000000000..377442dcf --- /dev/null +++ b/doc/1.6.1/language/string/prototype/endswith/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#endsWith + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#endsWith +

    + + + + +
    +
    +
    +
    +
    +
    String#endsWith(substring) → Boolean
    + + +

    Checks if the string ends with substring.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/escapehtml/index.html b/doc/1.6.1/language/string/prototype/escapehtml/index.html new file mode 100644 index 000000000..945e337c7 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/escapehtml/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#escapeHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#escapeHTML +

    + + + + +
    +
    +
    +
    +
    +
    String#escapeHTML() → String
    + + +

    Converts HTML special characters to their entity equivalents.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/evaljson/index.html b/doc/1.6.1/language/string/prototype/evaljson/index.html new file mode 100644 index 000000000..a3af2858c --- /dev/null +++ b/doc/1.6.1/language/string/prototype/evaljson/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.6.1 API documentation | String#evalJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#evalJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#evalJSON([sanitize = false]) → object
    + + +

    Evaluates the JSON in the string and returns the resulting object.

    + +

    If the optional sanitize parameter is set to true, the string is +checked for possible malicious attempts; if one is detected, eval +is not called.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/evalscripts/index.html b/doc/1.6.1/language/string/prototype/evalscripts/index.html new file mode 100644 index 000000000..8d697135b --- /dev/null +++ b/doc/1.6.1/language/string/prototype/evalscripts/index.html @@ -0,0 +1,203 @@ + + + + + Prototype v1.6.1 API documentation | String#evalScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#evalScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#evalScripts() → Array
    + + +

    Evaluates the content of any inline <script> block present in the string. +Returns an array containing the value returned by each script. +<script> blocks referencing external files will be treated as though +they were empty (the result for that position in the array will be undefined); +external files are not loaded and processed by evalScripts.

    + +

    About `evalScripts`, `var`s, and defining functions

    + +

    evalScripts evaluates script blocks, but this does not mean they are +evaluated in the global scope. They aren't, they're evaluated in the scope of +the evalScripts method. This has important ramifications for your scripts:

    + +
      +
    • Anything in your script declared with the var keyword will be +discarded momentarily after evaluation, and will be invisible to any +other scope.
    • +
    • If any <script> blocks define functions, they will need to be assigned to +properties of the window object.
    • +
    + +

    For example, this won't work:

    + +
    // This kind of script won't work if processed by evalScripts:
    +function coolFunc() {
    +  // Amazing stuff!
    +}
    +
    +
    + +

    Instead, use the following syntax:

    + +
    // This kind of script WILL work if processed by evalScripts:
    +window.coolFunc = function() {
    +  // Amazing stuff!
    +}
    +
    +
    + +

    (You can leave off the window. part of that, but it's bad form.)

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/extractscripts/index.html b/doc/1.6.1/language/string/prototype/extractscripts/index.html new file mode 100644 index 000000000..0a4b8e52b --- /dev/null +++ b/doc/1.6.1/language/string/prototype/extractscripts/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#extractScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#extractScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#extractScripts() → Array
    + + +

    Extracts the content of any script blocks present in the string and +returns them as an array of strings.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/gsub/index.html b/doc/1.6.1/language/string/prototype/gsub/index.html new file mode 100644 index 000000000..aacbc173e --- /dev/null +++ b/doc/1.6.1/language/string/prototype/gsub/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.6.1 API documentation | String#gsub + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#gsub +

    + + + + +
    +
    +
    +
    +
    +
    String#gsub(pattern, replacement) → String
    + + +

    Returns the string with every occurence of a given pattern replaced by either +a regular string, the returned value of a function or a Template string. +The pattern can be a string or a regular expression.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/include/index.html b/doc/1.6.1/language/string/prototype/include/index.html new file mode 100644 index 000000000..cd7a026f4 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/include/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#include +

    + + + + +
    +
    +
    +
    +
    +
    String#include(substring) → Boolean
    + + +

    Checks if the string contains substring.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/inspect/index.html b/doc/1.6.1/language/string/prototype/inspect/index.html new file mode 100644 index 000000000..acd6d4eaf --- /dev/null +++ b/doc/1.6.1/language/string/prototype/inspect/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#inspect +

    + + + + +
    +
    +
    +
    +
    +
    String#inspect([useDoubleQuotes = false]) → String
    + + +

    Returns a debug-oriented version of the string (i.e. wrapped in single or +double quotes, with backslashes and quotes escaped).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/interpolate/index.html b/doc/1.6.1/language/string/prototype/interpolate/index.html new file mode 100644 index 000000000..86950a452 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/interpolate/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#interpolate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#interpolate +

    + + + + +
    +
    +
    +
    +
    +
    String#interpolate(object[, pattern]) → String
    + + +

    Treats the string as a Template and fills it with object's +properties.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/isjson/index.html b/doc/1.6.1/language/string/prototype/isjson/index.html new file mode 100644 index 000000000..fac414146 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/isjson/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#isJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#isJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#isJSON() → Boolean
    + + +

    Check if the string is valid JSON by the use of regular expressions. +This security method is called internally.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/parsequery/index.html b/doc/1.6.1/language/string/prototype/parsequery/index.html new file mode 100644 index 000000000..bbb09cba2 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/parsequery/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#parseQuery + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#parseQuery +

    + + + + +
    +
    +
    +
    +
    +
    String#parseQuery([separator = '&']) → Object
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/scan/index.html b/doc/1.6.1/language/string/prototype/scan/index.html new file mode 100644 index 000000000..f20a52b21 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/scan/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.6.1 API documentation | String#scan + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#scan +

    + + + + +
    +
    +
    +
    +
    +
    String#scan(pattern, iterator) → String
    + + +

    Allows iterating over every occurrence of the given pattern (which can be a +string or a regular expression). +Returns the original string.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/startswith/index.html b/doc/1.6.1/language/string/prototype/startswith/index.html new file mode 100644 index 000000000..bd2c11c4c --- /dev/null +++ b/doc/1.6.1/language/string/prototype/startswith/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#startsWith + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#startsWith +

    + + + + +
    +
    +
    +
    +
    +
    String#startsWith(substring) → Boolean
    + + +

    Checks if the string starts with substring.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/strip/index.html b/doc/1.6.1/language/string/prototype/strip/index.html new file mode 100644 index 000000000..d273a7159 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/strip/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#strip + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#strip +

    + + + + +
    +
    +
    +
    +
    +
    String#strip() → String
    + + +

    Strips all leading and trailing whitespace from a string.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/stripscripts/index.html b/doc/1.6.1/language/string/prototype/stripscripts/index.html new file mode 100644 index 000000000..dbca1bf2f --- /dev/null +++ b/doc/1.6.1/language/string/prototype/stripscripts/index.html @@ -0,0 +1,178 @@ + + + + + Prototype v1.6.1 API documentation | String#stripScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#stripScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#stripScripts() → String
    + + +

    Strips a string of things that look like an HTML script blocks.

    + +

    Example

    + +
    "<p>This is a test.<script>alert("Look, a test!");</script>End of test</p>".stripScripts();
    +// => "<p>This is a test.End of test</p>"
    +
    +
    + +

    Caveat User

    + +

    Note that the processing stripScripts does is good enough for most purposes, +but you cannot rely on it for security purposes. If you're processing end-user-supplied +content, stripScripts is probably not sufficiently robust to prevent hack attacks.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/striptags/index.html b/doc/1.6.1/language/string/prototype/striptags/index.html new file mode 100644 index 000000000..18b446b19 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/striptags/index.html @@ -0,0 +1,178 @@ + + + + + Prototype v1.6.1 API documentation | String#stripTags + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#stripTags +

    + + + + +
    +
    +
    +
    +
    +
    String#stripTags() → String
    + + +

    Strips a string of any HTML tags.

    + +

    Note that stripTags will only strip HTML 4.01 tags — like div, +span, and abbr. It will not strip namespace-prefixed tags such +as h:table or xsl:template.

    + +

    Caveat User

    + +

    Note that the processing stripTags does is good enough for most purposes, but +you cannot rely on it for security purposes. If you're processing end-user-supplied +content, stripTags is probably not sufficiently robust to ensure that the content +is completely devoid of HTML tags in the case of a user intentionally trying to circumvent +tag restrictions. But then, you'll be running them through String#escapeHTML anyway, +won't you?

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/sub/index.html b/doc/1.6.1/language/string/prototype/sub/index.html new file mode 100644 index 000000000..785314e9f --- /dev/null +++ b/doc/1.6.1/language/string/prototype/sub/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.6.1 API documentation | String#sub + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#sub +

    + + + + +
    +
    +
    +
    +
    +
    String#sub(pattern, replacement[, count = 1]) → String
    + + +

    Returns a string with the first count occurrences of pattern replaced by either +a regular string, the returned value of a function or a Template string. +The pattern can be a string or a regular expression.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/succ/index.html b/doc/1.6.1/language/string/prototype/succ/index.html new file mode 100644 index 000000000..b33113738 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/succ/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.6.1 API documentation | String#succ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#succ +

    + + + + +
    +
    +
    +
    +
    +
    String#succ() → String
    + + +

    Used internally by ObjectRange. +Converts the last character of the string to the following character in +the Unicode alphabet.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/times/index.html b/doc/1.6.1/language/string/prototype/times/index.html new file mode 100644 index 000000000..6b97f0b67 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/times/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#times + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#times +

    + + + + +
    +
    +
    +
    +
    +
    String#times(count) → String
    + + +

    Concatenates the string count times.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/toarray/index.html b/doc/1.6.1/language/string/prototype/toarray/index.html new file mode 100644 index 000000000..def2c2f0b --- /dev/null +++ b/doc/1.6.1/language/string/prototype/toarray/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#toArray +

    + + + + +
    +
    +
    +
    +
    +
    String#toArray() → Array
    + + +

    Splits the string character-by-character and returns an array with +the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/tojson/index.html b/doc/1.6.1/language/string/prototype/tojson/index.html new file mode 100644 index 000000000..95f419c60 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/tojson/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.6.1 API documentation | String#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#toJSON() → String
    + + +

    Returns a JSON string.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/toqueryparams/index.html b/doc/1.6.1/language/string/prototype/toqueryparams/index.html new file mode 100644 index 000000000..7e2b696b4 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/toqueryparams/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#toQueryParams + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#toQueryParams +

    + + + + +
    +
    +
    +
    +
    +
    String#toQueryParams([separator = '&']) → Object
    + + +

    Parses a URI-like query string and returns an object composed of +parameter/value pairs.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/truncate/index.html b/doc/1.6.1/language/string/prototype/truncate/index.html new file mode 100644 index 000000000..2bb313ddc --- /dev/null +++ b/doc/1.6.1/language/string/prototype/truncate/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#truncate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#truncate +

    + + + + +
    +
    +
    +
    +
    +
    String#truncate([length = 30[, suffix = '...']]) → String
    + + +

    Truncates a string to given length and appends suffix to it (indicating +that it is only an excerpt).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/underscore/index.html b/doc/1.6.1/language/string/prototype/underscore/index.html new file mode 100644 index 000000000..ce507e660 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/underscore/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#underscore + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#underscore +

    + + + + +
    +
    +
    +
    +
    +
    String#underscore() → String
    + + +

    Converts a camelized string into a series of words separated by an +underscore (_).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/unescapehtml/index.html b/doc/1.6.1/language/string/prototype/unescapehtml/index.html new file mode 100644 index 000000000..aa8101b44 --- /dev/null +++ b/doc/1.6.1/language/string/prototype/unescapehtml/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#unescapeHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#unescapeHTML +

    + + + + +
    +
    +
    +
    +
    +
    String#unescapeHTML() → String
    + + +

    Strips tags and converts the entity forms of special HTML characters +to their normal form.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/string/prototype/unfilterjson/index.html b/doc/1.6.1/language/string/prototype/unfilterjson/index.html new file mode 100644 index 000000000..e832e26ff --- /dev/null +++ b/doc/1.6.1/language/string/prototype/unfilterjson/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.6.1 API documentation | String#unfilterJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#unfilterJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#unfilterJSON([filter = Prototype.JSONFilter]) → String
    + + +

    Strips comment delimiters around Ajax JSON or JavaScript responses. +This security method is called internally.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/template/index.html b/doc/1.6.1/language/template/index.html new file mode 100644 index 000000000..66a818cb7 --- /dev/null +++ b/doc/1.6.1/language/template/index.html @@ -0,0 +1,263 @@ + + + + + Prototype v1.6.1 API documentation | Template + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Template +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A class for sophisticated string interpolation.

    + +

    Any time you have a group of similar objects and you need to produce +formatted output for these objects, maybe inside a loop, you typically +resort to concatenating string literals with the object's fields:

    + +
    "The TV show " + title + " was created by " + author + ".";
    +
    +
    + +

    There's nothing wrong with this approach, except that it is hard to +visualize the output immediately just by glancing at the concatenation +expression. The Template class provides a much nicer and clearer way of +achieving this formatting.

    + +

    Straightforward templates

    + +

    The Template class uses a basic formatting syntax, similar to what is +used in Ruby. The templates are created from strings that have embedded +symbols in the form (e.g., #{fieldName}) that will be replaced by +actual values when the template is applied (evaluated) to an object.

    + +
    // the template (our formatting expression)
    +var myTemplate = new Template(
    + 'The TV show #{title} was created by #{author}.');
    + // our data to be formatted by the template
    +var show = {
    +  title: 'The Simpsons',
    +  author: 'Matt Groening',
    +  network: 'FOX'
    +};
    + // let's format our data
    +myTemplate.evaluate(show);
    +// -> "The TV show The Simpsons was created by Matt Groening."
    +
    +
    + +

    Templates are meant to be reused

    + +

    As the example illustrates, Template objects are not tied to specific +data. The data is bound to the template only during the evaluation of the +template, without affecting the template itself. The next example shows the +same template being used with a handful of distinct objects.

    + +
    // creating a few similar objects
    +var conversion1 = { from: 'meters', to: 'feet', factor: 3.28 };
    +var conversion2 = { from: 'kilojoules', to: 'BTUs', factor: 0.9478 };
    +var conversion3 = { from: 'megabytes', to: 'gigabytes', factor: 1024 };
    + // the template
    +var templ = new Template(
    + 'Multiply by #{factor} to convert from #{from} to #{to}.');
    + // let's format each object
    +[conversion1, conversion2, conversion3].each( function(conv){
    +    templ.evaluate(conv);
    +});
    +// -> Multiply by 3.28 to convert from meters to feet.
    +// -> Multiply by 0.9478 to convert from kilojoules to BTUs.
    +// -> Multiply by 1024 to convert from megabytes to gigabytes.
    +
    +
    + +

    Escape sequence

    + +

    There's always the chance that one day you'll need to have a literal in your +template that looks like a symbol, but is not supposed to be replaced. For +these situations there's an escape character: the backslash (\).

    + +
    // NOTE: you're seeing two backslashes here because the backslash
    +// is also an escape character in JavaScript strings, so a literal
    +// backslash is represented by two backslashes.
    +var t = new Template(
    + 'in #{lang} we also use the \\#{variable} syntax for templates.');
    +var data = { lang:'Ruby', variable: '(not used)' };
    +t.evaluate(data);
    +// -> in Ruby we also use the #{variable} syntax for templates.
    +
    +
    + +

    Custom syntaxes

    + +

    The default syntax of the template strings will probably be enough for most +scenarios. In the rare occasion where the default Ruby-like syntax is +inadequate, there's a provision for customization. Template's +constructor accepts an optional second argument that is a regular expression +object to match the replaceable symbols in the template string. Let's put +together a template that uses a syntax similar to the ubiquitous <&#38;= %> +constructs:

    + +
    // matches symbols like '<&#38;= field %>'
    +var syntax = /(^|.|\r|\n)(\<%=\s*(\w+)\s*%\>)/;
    + var t = new Template(
    + '<div>Name: <b><&#38;= name %></b>, Age: <b><&#38;=age%></b></div>',
    + syntax);
    +t.evaluate( {name: 'John Smith', age: 26} );
    +// -> <div>Name: <b>John Smith</b>, Age: <b>26</b></div>
    +
    +
    + +

    There are important constraints to any custom syntax. Any syntax must +provide at least three groupings in the regular expression. The first +grouping is to capture what comes before the symbol, to detect the backslash +escape character (no, you cannot use a different character). The second +grouping captures the entire symbol and will be completely replaced upon +evaluation. Lastly, the third required grouping captures the name of the +field inside the symbol.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Template

    +
    +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/template/new/index.html b/doc/1.6.1/language/template/new/index.html new file mode 100644 index 000000000..257964a17 --- /dev/null +++ b/doc/1.6.1/language/template/new/index.html @@ -0,0 +1,138 @@ + + + + + Prototype v1.6.1 API documentation | new Template + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Template +

    + + + + +
    +
    +
    +
    +
    +
    new(template[, pattern = Template.Pattern])
    + + +

    Creates a Template object.

    + +

    The optional pattern argument expects a RegExp that defines a custom +syntax for the replaceable symbols in template.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/template/prototype/evaluate/index.html b/doc/1.6.1/language/template/prototype/evaluate/index.html new file mode 100644 index 000000000..74e3ef44a --- /dev/null +++ b/doc/1.6.1/language/template/prototype/evaluate/index.html @@ -0,0 +1,136 @@ + + + + + Prototype v1.6.1 API documentation | Template#evaluate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Template#evaluate +

    + + + + +
    +
    +
    +
    +
    +
    Template#evaluate(object) → String
    + + +

    Applies the template to object's data, producing a formatted string +with symbols replaced by object's corresponding properties.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/language/try/index.html b/doc/1.6.1/language/try/index.html new file mode 100644 index 000000000..5f59805c8 --- /dev/null +++ b/doc/1.6.1/language/try/index.html @@ -0,0 +1,138 @@ + + + + + Prototype v1.6.1 API documentation | Try + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Try +

    + + + + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.6.1/language/try/these/index.html b/doc/1.6.1/language/try/these/index.html new file mode 100644 index 000000000..4952c470c --- /dev/null +++ b/doc/1.6.1/language/try/these/index.html @@ -0,0 +1,142 @@ + + + + + Prototype v1.6.1 API documentation | Try.these + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Try.these +

    + + + + +
    +
    +
    +
    +
    +
    Try.these(function...) → ?
    +
      +
    • + function + (Function) + – A function that may throw an exception. +
    • +
    + + +

    Accepts an arbitrary number of functions and returns the result of the +first one that doesn't throw an error.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.6.1/stylesheets/api.css b/doc/1.6.1/stylesheets/api.css new file mode 100644 index 000000000..7e28842f8 --- /dev/null +++ b/doc/1.6.1/stylesheets/api.css @@ -0,0 +1,687 @@ +/* The "section" class implicitly needs a clearfix; adding it here for convenience. */ + +.clearfix:after, +.section:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; +} + +.clearfix, .section { + display: inline-block; +} + +html[xmlns] .clearfix, +html[xmlns] .section { + display: block; +} + +* html .clearfix, +* html .section { + height: 1%; +} + +span.replaced { visibility: hidden; } +span.hidden { display: none; } + + +body { + font-family: Verdana, sans-serif; + font-size: 82.5%; + line-height: 1.5em; + margin: 0; + padding: 0; +} + + body * { + margin: 0; + padding: 0; + } + +h1, h2, h3, h4, h5, h6 { + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; +} + +pre { + white-space: pre-wrap; /* CSS 3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +a img { + border: 0; +} + +ul, li { + list-style-type: none; +} + +ol, ul { + margin: 0 0 15px; +} + +code, pre { + font-family: "Panic Sans", "Bitstream Vera Sans Mono", Monaco, Consolas, Andale Mono, monospace; + font-size: 12px; +} + +#page a.img, +#page a.img:link, +#page a.img:visited { + border: 0; +} + +.content { + padding-left: 120px; + margin: 0 auto; +} + +#page { + margin: 0; + position: fixed; + top: 0; + bottom: 0; + right: 0; + left: 241px; + overflow-y: scroll; + overflow-x: auto; +} + + +/* MASTHEAD */ + +.masthead { + margin-top: 31px; + height: 75px; + padding: 1px 0; + background: url(../images/header-stripe-small.png) repeat-x; +} + +h1.logo { + width: 236px; + height: 150px; + background: url(../images/header-logo-small.png) no-repeat; +} + + h1.logo a { + text-decoration: none; + } + +/* BREADCRUMBS */ + +ul.breadcrumbs { + margin-left: 120px; + padding-left: 120px; + list-style-type: none; +} + + ul.breadcrumbs li { + float: left; + list-style-type: none; + margin-left: 0; + margin-right: 0.4em; + } + +#deprecated { + position: absolute; + right: 0; + top: 0; +} + +#deprecated img { + display: block; + border: 0; +} + + +/* PAGE CONTENT */ + +.page-content { + width: 715px; + margin: 0 0 30px 0; +} + + .page-content h2.page-title { + margin: 0 0 15px 120px; + line-height: 100%; + font-size: 27px; + letter-spacing: -1px; + color: #444; + } + + .page-introduction { + margin-left: 120px; + margin-bottom: 25px; + } + + .page-content a, + .page-content a:link { + color: #036; + border-bottom: 1px solid #036; + text-decoration: none; + } + + .page-content a:visited { + border-bottom: 1px solid #bbb; + } + + .page-content ul, + .page-content ol { + margin: 10px 0; + } + + .page-content li { + margin: 5px 0 8px 20px; + list-style-type: disc; + } + + .page-content p { + margin: 0 0 0.8em; + } + + .page-content code { + background-color: #f0f0f0; + border: 1px solid #ccc; + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + padding: 0 3px; + } + + .page-content pre { + color: #333; + background-color: #f0f0ff; + border: 1px solid #dde; + padding: 3px 5px; + margin: 0 0 1em; + } + + .page-content pre code { + background-color: transparent; + border: 0; + padding: 0; + line-height: 100%; + } + + + .page-content code { + + } + + .page-content h1 { + font-size: 27px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h2 { + font-size: 23px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h3 { + font-size: 20px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h4 { + font-size: 17px; + color: #555; + margin: 1.0em 0 0.6em; + } + + .page-content h5 { + font-size: 15px; + color: #2a2a2a; + margin: 1.0em 0 0.6em; + } + + .page-content h6 { + font-size: 14px; + color: #000; + margin: 1.0em 0 0.6em; + } + +/* PAGE SECTIONS */ + +.section { + margin: 10px 0 15px; +} + + .section-title { + width: 110px; + float: left; + margin-right: 10px; + padding-right: 0; + padding-bottom: 10px; + text-align: right; + overflow: hidden; + } + + .section-title h3 { + color: #999; + font-size: 14px; + line-height: 110%; + margin-top: 3px; + padding-right: 10px; + padding-bottom: 5px; + } + + .section-content { + width: 595px; + float: left; + } + + +/* API STYLES */ + +.page-title .type { + display: block; + text-transform: uppercase; + font-size: 14px; + color: #aaa; +} + + +ul.section-list { + list-style-type: none; + margin-top: 0; +} + + ul.section-list li { + list-style-type: none; + margin: 0 0 15px; + } + + ul.section-list li h4 { + margin-top: 0; + } + +ul.method-list { + margin-top: 0; +} + + ul.method-list li { + float: left; + margin: 0 5px 3px 0; + list-style-type: none; + padding-bottom: 0; + } + + ul.method-list li a, + ul.method-list li a:link { + text-decoration: none; + border: 0; + } + +ul.method-details-list { + margin-top: 0; +} + + li.method-description { + margin: 0 0 2.0em; + list-style-type: none; + } + + .method-description h4 { + margin: 0 0 0.6em; + line-height: 90%; + } + + .method-description p { + margin: 0.8em 0; + } + + + .method-description .method-permalink a { + color: #aaa; + text-decoration: none; + border-bottom: 0; + font-size: 14px; +} + +h4.inherited { + clear: left; + font-size: 15px; + font-style: italic; +} + +pre.syntax { + margin-bottom: 5px; +} + +ul.argument-list { + font-size: 12px; + padding: 0; + margin: 0; +} + + ul.argument-list li { + line-height: 140%; + margin-top: 0px; + margin-bottom: 5px; + } + + ul.argument-list li code { + font-size: 11px; + } + + ul.argument-list .argument-name { + background-color: #eeffee; + border-color: #6b6; + } + + +/* SECTION ICONS */ + +.page-content .section .section-title h3 { + padding-right: 24px; + background-position: right 0; + background-repeat: no-repeat; +} + +.section-constructor .section-title h3 { + background-image: url(../images/constructor.png); +} + +.section-method-list .section-title h3 { + background-image: url(../images/method.png); +} + +.section-class_methods .section-title h3 { + background-image: url(../images/class_method.png); +} + +.section-class_properties .section-title h3 { + background-image: url(../images/class_property.png); +} + +.section-instance_methods .section-title h3 { + background-image: url(../images/instance_method.png); +} + +.section-instance_properties .section-title h3 { + background-image: url(../images/instance_property.png); +} + +.section-mixins .section-title h3 { + background-image: url(../images/mixin.png); +} + +.section-classes .section-title h3 { + background-image: url(../images/class.png); +} + +.section-namespaces .section-title h3 { + background-image: url(../images/namespace.png); +} + +.section-sections .section-title h3 { + background-image: url(../images/section.png); +} + +.section-utilities .section-title h3 { + background-image: url(../images/utility.png); +} + +.section-description .section-title h3 { + background-image: url(../images/description.png); +} + +.section-subclasses .section-title h3 { + background-image: url(../images/subclass.png); +} + +.section-superclass .section-title h3 { + background-image: url(../images/superclass.png); +} + +/* notes */ + +p.note, +p.alias, +p.related-to { + font-size: 11px; + line-height: 14px; + padding: 5px 20px 5px 60px; + background-repeat: no-repeat; + background-position: 20px 50%; + border: 1px solid #000; +} + +p.note { + background-color: #f0f0f4; + background-image: url(../images/information.png); + border-color: #69c; +} + +p.alias { + background-color: #fff6de; + background-image: url(../images/alias.png); + border-color: #cc9; +} + +p.related-to { + background-color: #f4f0f4; + background-image: url(../images/related_to.png); + border-color: #c9c; +} + +/* SIDEBAR */ + +#sidebar { + position: fixed; + top: 0; + bottom: 0; + left: 0; + width: 240px; + background: #fff; + font-size: 13px; +} + +#sidebar form.search-ribbon { + margin: 0; + height: 24px; + border-right: 1px solid #636363; + padding: 4px 0 3px; + border-bottom: 1px solid #587e93; + background: url(../images/search-background.png) repeat-x 0 0; + text-align: center; +} + +/* Keep these around for `Control.Tabs`. */ +.sidebar-tabs { display: none; } + +.menu-items ul { + margin: 0; +} + + .menu-items ul li { + list-style-type: none; + padding-left: 0; + margin-left: 0; + } + + .menu-items ul .menu-item a { + padding-left: 38px; + background-position: 16px 50%; + } + + .menu-items ul ul .menu-item a { + padding-left: 48px; + background-position: 26px 50%; + } + + .menu-items ul ul ul .menu-item a { + padding-left: 58px; + background-position: 36px 50%; + } + + .menu-items ul ul ul ul .menu-item a { + padding-left: 68px; + background-position: 46px 50%; + } + + + + .menu-item a, + .menu-item a:link { + display: block; + padding: 3px 10px 3px 28px; + background-position: 6px 50%; + background-repeat: no-repeat; + text-align: left; + text-decoration: none; + color: #333; + border-top: 1px solid #fff; + border-bottom: 1px solid #fff; + white-space: nowrap; + } + + .menu-item a:hover, + .menu-item a.highlighted, + #sidebar .highlighted a { + border-top: 1px solid #69f; + border-bottom: 1px solid #69f; + background-color: #f0f0ff; + } + + .menu-item a.current, + #sidebar .current a { + border-top: 1px solid #f0f0ff; + border-bottom: 1px solid #f0f0ff; + background-color: #f0f0ff; + } + + .menu-item a.current-parent, + #sidebar .current-parent a { + border-top: 1px solid #f0f0ff; + border-bottom: 1px solid #f0f0ff; + background-color: #f0f0ff; + } + + .menu-item a.class-method { + background-image: url(../images/class_method.png); + } + + .menu-item a.instance-method { + background-image: url(../images/instance_method.png); + } + + .menu-item a.class { + background-image: url(../images/class.png); + } + + .menu-item a.constructor { + background-image: url(../images/constructor.png); + } + + .menu-item a.class-property { + background-image: url(../images/class_property.png); + } + + .menu-item a.instance-property { + background-image: url(../images/instance_property.png); + } + + .menu-item a.namespace { + background-image: url(../images/namespace.png); + } + + .menu-item a.mixin { + background-image: url(../images/mixin.png); + } + + .menu-item a.utility { + background-image: url(../images/utility.png); + } + + .menu-item a.section { + margin: 0; + background-image: url(../images/section.png); + } + + #api_menu .menu-item a.section { + height: 22px; + font-weight: normal; + color: #a5a5a5; + margin-top: 0; + margin-bottom: 0; + border-top: 1px solid #000; + border-bottom: 1px solid #000; + background: url(../images/section-background.png) repeat-x 0 0; + } + +.menu-section { + margin-bottom: 1.0em; +} + +#menu_pane { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + width: 239px; + border-right: 1px solid #636363; + overflow-y: scroll; + overflow-x: hidden; +} + +#search_pane { + width: 239px; + border-right: 1px solid #636363; + position: absolute; + top: 32px; + bottom: 0; + left: 0; +} + + #search_results { + margin: 0; + padding: 0; + overflow-y: scroll; + overflow-x: hidden; + position: absolute; + top: 0; + bottom: 0; + width: 239px; + } + +#search { + width: 200px; + padding: 2px 3px; +} + +input.ghosted { + font-style: italic; + color: #aaa; +} + + +/* FOOTER */ + +#footer { + color: #bbb; + width: 595px; + margin-left: 120px; + margin-top: 30px; + border-top: 1px solid #ccc; + font-size: 10px; + padding: 1em 0; +} + + #footer a, + #footer a:link { + color: #999; + } + +#src_code_href { + float: right; +} \ No newline at end of file diff --git a/doc/1.6.1/stylesheets/pygments.css b/doc/1.6.1/stylesheets/pygments.css new file mode 100644 index 000000000..56dee2899 --- /dev/null +++ b/doc/1.6.1/stylesheets/pygments.css @@ -0,0 +1,62 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #408080; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ +.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #808080 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #7D9029 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/doc/1.7_rc1/ajax/ajax/activerequestcount/index.html b/doc/1.7_rc1/ajax/ajax/activerequestcount/index.html new file mode 100644 index 000000000..d11fb577d --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/activerequestcount/index.html @@ -0,0 +1,141 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.activeRequestCount + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Ajax.activeRequestCount +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.activeRequestCount → Number
    + + +

    Represents the number of active XHR requests triggered through +Ajax.Request, Ajax.Updater, or Ajax.PeriodicalUpdater.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/index.html b/doc/1.7_rc1/ajax/ajax/index.html new file mode 100644 index 000000000..3dd3d27cf --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/index.html @@ -0,0 +1,195 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Ajax +

    + + + + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Ajax.Responders

      + +

      A repository of global listeners notified about every step of +Prototype-based Ajax requests.

      +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Ajax.PeriodicalUpdater

      + +

      Periodically performs an Ajax request and updates a container's contents +based on the response text.

      +
    • +
    • +

      Ajax.Request

      + +

      Initiates and processes an Ajax request.

      +
    • +
    • +

      Ajax.Response

      + +

      A wrapper class around XmlHttpRequest for dealing with HTTP responses +of Ajax requests.

      +
    • +
    • +

      Ajax.Updater

      + +

      A class that performs an Ajax request and updates a container's contents +with the contents of the response.

      +
    • +
    +
    +
    + + + + + + + + +
    +
    +

    Class properties

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/periodicalupdater/index.html b/doc/1.7_rc1/ajax/ajax/periodicalupdater/index.html new file mode 100644 index 000000000..94e8f594f --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/periodicalupdater/index.html @@ -0,0 +1,209 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.PeriodicalUpdater + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Ajax.PeriodicalUpdater +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Periodically performs an Ajax request and updates a container's contents +based on the response text.

    + +

    Ajax.PeriodicalUpdater behaves like Ajax.Updater, but performs the +update at a prescribed interval, rather than only once. (Note that it is +not a subclass of Ajax.Updater; it's a wrapper around it.)

    + +

    This class addresses the common need of periodical update, as required by +all sorts of "polling" mechanisms (e.g., an online chatroom or an online +mail client).

    + +

    The basic idea is to run a regular Ajax.Updater at regular intervals, +keeping track of the response text so it can (optionally) react to +receiving the exact same response consecutively.

    + +
    Additional options
    + +

    Ajax.PeriodicalUpdater features all the common options and callbacks +described in the Ajaxplus those added by +Ajax.Updater.

    + +

    It also provides two new options:

    + +
      +
    • frequency (Number; default is 2): How long, in seconds, to wait +between the end of one request and the beginning of the next.
    • +
    • decay (Number; default is 1): The rate at which the frequency +grows when the response received is exactly the same as the previous. +The default of 1 means frequency will never grow; override the +default if a stale response implies it's worthwhile to poll less often. +If decay is set to 2, for instance, frequency will double +(2 seconds, 4 seconds, 8 seconds...) each consecutive time the result +is the same; when the result is different once again, frequency will +revert to its original value.
    • +
    + +
    Disabling and re-enabling a Ajax.PeriodicalUpdater
    + +

    You can hit the brakes on a running Ajax.PeriodicalUpdater by calling +Ajax.PeriodicalUpdater#stop. If you wish to re-enable it later, call +Ajax.PeriodicalUpdater#start.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/periodicalupdater/new/index.html b/doc/1.7_rc1/ajax/ajax/periodicalupdater/new/index.html new file mode 100644 index 000000000..ac400ff19 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/periodicalupdater/new/index.html @@ -0,0 +1,310 @@ + + + + + Prototype v1.7_rc1 API documentation | new Ajax.PeriodicalUpdater + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Ajax.PeriodicalUpdater +

    + + + + +
    +
    +
    +
    +
    +
    new(container, url[, options])
    +
      +
    • + container + (String | Element) + – The DOM element whose contents to update as a result of the Ajax request. Can be a DOM node or a string that identifies a node's ID. +
    • +
    • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
    • +
    • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
    • +
    + + +

    Creates a new Ajax.PeriodicalUpdater.

    + +

    Periodically performs an AJAX request and updates a container's contents +based on the response text. Offers a mechanism for "decay," which lets it +trigger at widening intervals while the response is unchanged.

    + +

    This object addresses the common need of periodical update, which is used +by all sorts of "polling" mechanisms (e.g. in an online chatroom or an +online mail client).

    + +

    The basic idea is to run a regular Ajax.Updater at +regular intervals, monitoring changes in the response text if the decay +option (see below) is active.

    + +
    Additional options
    + +

    Ajax.PeriodicalUpdater features all the common options and callbacks +(see the Ajax for more information), plus those added by +Ajax.Updater. It also provides two new options that deal with the +original period, and its decay rate (how Rocket Scientist does that make +us sound, uh?!).

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDefaultDescription
    frequency2Okay, this is not a frequency (e.g 0.5Hz), but a period (i.e. a number of seconds). +Don't kill me, I didn't write this one! This is the minimum interval at which AJAX +requests are made. You don't want to make it too short (otherwise you may very well +end up with multiple requests in parallel, if they take longer to process and return), +but you technically can provide a number below one, e.g. 0.75 second.
    decay1This controls the rate at which the request interval grows when the response is +unchanged. It is used as a multiplier on the current period (which starts at the original +value of the frequency parameter). Every time a request returns an unchanged +response text, the current period is multiplied by the decay. Therefore, the default +value means regular requests (no change of interval). Values higher than one will +yield growing intervals. Values below one are dangerous: the longer the response text +stays the same, the more often you'll check, until the interval is so short your browser +is left with no other choice than suicide. Note that, as soon as the response text +does change, the current period resets to the original one.
    + +

    To better understand decay, here is a small sequence of calls from the +following example:

    + +
    new Ajax.PeriodicalUpdater('items', '/items', {
    +  method: 'get', frequency: 3, decay: 2
    +});
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Call#When?Decay beforeResponse changed?Decay afterNext periodComments
    100:002n/a13Response is deemed changed, since there is no prior response to compare to!
    200:031yes13Response did change again: we "reset" to 1, which was already the decay.
    300:061no26Response didn't change: decay augments by the decay option factor: +we're waiting longer now…
    400:122no412Still no change, doubling again.
    500:244no824Jesus, is this thing going to change or what?
    600:488yes13Ah, finally! Resetting decay to 1, and therefore using the original period.
    + +
    Disabling and re-enabling a Ajax.PeriodicalUpdater
    + +

    You can pull the brake on a running Ajax.PeriodicalUpdater by simply +calling its stop method. If you wish to re-enable it later, just call +its start method. Both take no argument.

    + +
    Beware! Not a specialization!
    + +

    Ajax.PeriodicalUpdater is not a specialization of Ajax.Updater, +despite its name. When using it, do not expect to be able to use methods +normally provided by Ajax.Request and "inherited" by Ajax.Updater, +such as evalJSON or getHeader. Also the onComplete callback is +hijacked to be used for update management, so if you wish to be notified +of every successful request, use onSuccess instead (beware: it will get +called before the update is performed).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/periodicalupdater/prototype/start/index.html b/doc/1.7_rc1/ajax/ajax/periodicalupdater/prototype/start/index.html new file mode 100644 index 000000000..b6eec1fae --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/periodicalupdater/prototype/start/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.PeriodicalUpdater#start + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.PeriodicalUpdater#start +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.PeriodicalUpdater#start() → undefined
    + + +

    Starts the periodical updater (if it had previously been stopped with +Ajax.PeriodicalUpdater#stop).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/periodicalupdater/prototype/stop/index.html b/doc/1.7_rc1/ajax/ajax/periodicalupdater/prototype/stop/index.html new file mode 100644 index 000000000..0c2bb68cc --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/periodicalupdater/prototype/stop/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.PeriodicalUpdater#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.PeriodicalUpdater#stop +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.PeriodicalUpdater#stop() → undefined
    + + +

    Stops the periodical updater.

    + +

    Also calls the onComplete callback, if one has been defined.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/request/index.html b/doc/1.7_rc1/ajax/ajax/request/index.html new file mode 100644 index 000000000..654f10733 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/request/index.html @@ -0,0 +1,338 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Ajax.Request +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Initiates and processes an Ajax request.

    + +

    Ajax.Request is a general-purpose class for making HTTP requests which +handles the life-cycle of the request, handles the boilerplate, and lets +you plug in callback functions for your custom needs.

    + +

    In the optional options hash, you usually provide an onComplete and/or +onSuccess callback, unless you're in the edge case where you're getting a +JavaScript-typed response, that will automatically be eval'd.

    + +

    For a full list of common options and callbacks, see "Ajax options" heading +of the Ajax.

    + +
    A basic example
    + +
    new Ajax.Request('/your/url', {
    +  onSuccess: function(response) {
    +    // Handle the response content...
    +  }
    +});
    +
    +
    + +
    Request life-cycle
    + +

    Underneath our nice requester objects lies, of course, XMLHttpRequest. The +defined life-cycle is as follows:

    + +
      +
    1. Created
    2. +
    3. Initialized
    4. +
    5. Request sent
    6. +
    7. Response being received (can occur many times, as packets come in)
    8. +
    9. Response received, request complete
    10. +
    + +

    As you can see under the "Ajax options" heading of the Ajax, +Prototype's AJAX objects define a whole slew of callbacks, which are +triggered in the following order:

    + +
      +
    1. onCreate (this is actually a callback reserved to Ajax.Responders)
    2. +
    3. onUninitialized (maps on Created)
    4. +
    5. onLoading (maps on Initialized)
    6. +
    7. onLoaded (maps on Request sent)
    8. +
    9. onInteractive (maps on Response being received)
    10. +
    11. onXYZ (numerical response status code), onSuccess or onFailure (see below)
    12. +
    13. onComplete
    14. +
    + +

    The two last steps both map on Response received, in that order. If a +status-specific callback is defined, it gets invoked. Otherwise, if +onSuccess is defined and the response is deemed a success (see below), it +is invoked. Otherwise, if onFailure is defined and the response is not +deemed a sucess, it is invoked. Only after that potential first callback is +onComplete called.

    + +
    A note on portability
    + +

    Depending on how your browser implements XMLHttpRequest, one or more +callbacks may never be invoked. In particular, onLoaded and +onInteractive are not a 100% safe bet so far. However, the global +onCreate, onUninitialized and the two final steps are very much +guaranteed.

    + +
    onSuccess and onFailure, the under-used callbacks
    + +

    Way too many people use Ajax.Request in a similar manner to raw XHR, +defining only an onComplete callback even when they're only interested in +"successful" responses, thereby testing it by hand:

    + +
    // This is too bad, there's better!
    +new Ajax.Request('/your/url', {
    +  onComplete: function(response) {
    +    if (200 == response.status)
    +      // yada yada yada
    +  }
    +});
    +
    +
    + +

    First, as described below, you could use better "success" detection: success +is generally defined, HTTP-wise, as either no response status or a "2xy" +response status (e.g., 201 is a success, too). See the example below.

    + +

    Second, you could dispense with status testing altogether! Prototype adds +callbacks specific to success and failure, which we listed above. Here's +what you could do if you're only interested in success, for instance:

    + +
    new Ajax.Request('/your/url', {
    +  onSuccess: function(response) {
    +      // yada yada yada
    +  }
    +});
    +
    +
    + +
    Automatic JavaScript response evaluation
    + +

    If an Ajax request follows the same-origin policy and its response +has a JavaScript-related Content-type, the content of the responseText +property will automatically be passed to eval.

    + +

    In other words: you don't even need to provide a callback to leverage +pure-JavaScript Ajax responses. This is the convention that drives Rails's +RJS.

    + +

    The list of JavaScript-related MIME-types handled by Prototype is:

    + +
      +
    • application/ecmascript
    • +
    • application/javascript
    • +
    • application/x-ecmascript
    • +
    • application/x-javascript
    • +
    • text/ecmascript
    • +
    • text/javascript
    • +
    • text/x-ecmascript
    • +
    • text/x-javascript
    • +
    + +

    The MIME-type string is examined in a case-insensitive manner.

    + +
    Methods you may find useful
    + +

    Instances of the Ajax.Request object provide several methods that come +in handy in your callback functions, especially once the request is complete.

    + +
    Is the response a successful one?
    + +

    The Ajax.Request#success method examines the XHR object's status +property and follows general HTTP guidelines: unknown status is deemed +successful, as is the whole 2xy status code family. It's a generally +better way of testing your response than the usual +200 == transport.status.

    + +
    Getting HTTP response headers
    + +

    While you can obtain response headers from the XHR object using its +getResponseHeader method, this makes for verbose code, and several +implementations raise an exception when the header is not found. To make +this easier, you can use the Ajax.Response#getHeader method, which +delegates to the longer version and returns null if an exception occurs:

    + +
    new Ajax.Request('/your/url', {
    +  onSuccess: function(response) {
    +    // Note how we brace against null values
    +    if ((response.getHeader('Server') || '').match(/Apache/))
    +      ++gApacheCount;
    +    // Remainder of the code
    +  }
    +});
    +
    +
    + +
    Evaluating JSON headers
    + +

    Some backends will return JSON not as response text, but in the X-JSON +header. In this case, you don't even need to evaluate the returned JSON +yourself, as Prototype automatically does so. It passes the result as the +headerJSON property of the Ajax.Response object. Note that if there +is no such header — or its contents are invalid — headerJSON +will be set to null.

    + +
    new Ajax.Request('/your/url', {
    +  onSuccess: function(transport) {
    +    transport.headerJSON
    +  }
    +});
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/request/new/index.html b/doc/1.7_rc1/ajax/ajax/request/new/index.html new file mode 100644 index 000000000..072c012a8 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/request/new/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | new Ajax.Request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Ajax.Request +

    + + + + +
    +
    +
    +
    +
    +
    new(url[, options])
    +
      +
    • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
    • +
    • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
    • +
    + + +

    Creates a new Ajax.Request.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/request/prototype/getheader/index.html b/doc/1.7_rc1/ajax/ajax/request/prototype/getheader/index.html new file mode 100644 index 000000000..b31ba4e8c --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/request/prototype/getheader/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Request#getHeader + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Request#getHeader +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Request#getHeader(name) → String | null
    +
      +
    • + name + (String) + – The name of an HTTP header that may have been part of the response. +
    • +
    + + +

    Returns the value of the given response header, or null if that header +was not found.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/request/prototype/success/index.html b/doc/1.7_rc1/ajax/ajax/request/prototype/success/index.html new file mode 100644 index 000000000..4e476cc8b --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/request/prototype/success/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Request#success + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Request#success +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Request#success() → Boolean
    + + +

    Tests whether the request was successful.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/responders/index.html b/doc/1.7_rc1/ajax/ajax/responders/index.html new file mode 100644 index 000000000..846f01d51 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/responders/index.html @@ -0,0 +1,223 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Responders + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Ajax.Responders +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A repository of global listeners notified about every step of +Prototype-based Ajax requests.

    + +

    Sometimes, you need to provide generic behaviors over all Ajax operations +happening on the page (through Ajax.Request, Ajax.Updater or +Ajax.PeriodicalUpdater).

    + +

    For instance, you might want to automatically show an indicator when an +Ajax request is ongoing, and hide it when none are. You may well want to +factor out exception handling as well, logging those somewhere on the page +in a custom fashion. The possibilities are myriad.

    + +

    To achieve this, Prototype provides Ajax.Responders, which lets you +register (and, if you wish, unregister later) responders, which are +objects with specially-named methods. These names come from a set of +general callbacks corresponding to different points in time (or outcomes) +of an Ajax request's life cycle.

    + +

    For instance, Prototype automatically registers a responder that maintains +a nifty variable: Ajax.activeRequestCount. This represents, at a given +time, the number of currently active Ajax requests — by monitoring their +onCreate and onComplete events. The code for this is fairly simple:

    + +
    Ajax.Responders.register({
    +  onCreate: function() {
    +    Ajax.activeRequestCount++;
    +  },
    +  onComplete: function() {
    +    Ajax.activeRequestCount--;
    +  }
    +});
    +
    +
    + +
    Responder callbacks
    + +

    The callbacks for responders are similar to the callbacks described in +the Ajax, but take a different signature. They're invoked with +three parameters: the requester object (i.e., the corresponding "instance" +of Ajax.Request), the XMLHttpRequest object, and the result of +evaluating the X-JSON response header, if any (can be null). They also +execute in the context of the responder, bound to the this reference.

    + +
      +
    • onCreate: Triggered whenever a requester object from the Ajax +namespace is created, after its parameters are adjusted and before its +XHR connection is opened. This takes two arguments: the requester +object and the underlying XHR object.
    • +
    • onUninitialized (Not guaranteed): Invoked just after the XHR object +is created.
    • +
    • onLoading (Not guaranteed): Triggered when the underlying XHR object +is being setup, and its connection opened.
    • +
    • onLoaded (Not guaranteed): Triggered once the underlying XHR object +is setup, the connection is open, and it is ready to send its actual +request.
    • +
    • onInteractive (Not guaranteed): Triggered whenever the requester +receives a part of the response (but not the final part), should it +be sent in several packets.
    • +
    • onException: Triggered whenever an XHR error arises. Has a custom +signature: the first argument is the requester (i.e. an Ajax.Request +instance), and the second is the exception object.
    • +
    • onComplete: Triggered at the very end of a request's life-cycle, after +the request completes, status-specific callbacks are called, and possible +automatic behaviors are processed. Guaranteed to run regardless of what +happened during the request.
    • +
    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/responders/register/index.html b/doc/1.7_rc1/ajax/ajax/responders/register/index.html new file mode 100644 index 000000000..4cf9e15fb --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/responders/register/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Responders.register + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Ajax.Responders.register +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Responders.register(responder) → undefined
    +
      +
    • + responder + (Object) + – A list of functions with keys corresponding to the names of possible callbacks. +
    • +
    + + +

    Add a group of responders to all Ajax requests.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/responders/unregister/index.html b/doc/1.7_rc1/ajax/ajax/responders/unregister/index.html new file mode 100644 index 000000000..0ae766cb1 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/responders/unregister/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Responders.unregister + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Ajax.Responders.unregister +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Responders.unregister(responder) → undefined
    +
      +
    • + responder + (Object) + – A list of functions with keys corresponding to the names of possible callbacks. +
    • +
    + + +

    Remove a previously-added group of responders.

    + +

    As always, unregistering something requires you to use the very same +object you used at registration. If you plan to use unregister, be sure +to assign your responder to a variable before passing it into +Ajax.Responders#register — don't pass it an object literal.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/index.html b/doc/1.7_rc1/ajax/ajax/response/index.html new file mode 100644 index 000000000..b8dde8dca --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Ajax.Response +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A wrapper class around XmlHttpRequest for dealing with HTTP responses +of Ajax requests.

    + +

    An instance of Ajax.Response is passed as the first argument of all Ajax +requests' callbacks. You will not need to create instances of +Ajax.Response yourself.

    +
    +
    + + + + + + + + + + +
    +
    +

    Instance properties

    +
    + +
    + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/getallheaders/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/getallheaders/index.html new file mode 100644 index 000000000..ab7c5f2f2 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/getallheaders/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#getAllHeaders + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Response#getAllHeaders +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#getAllHeaders() → String | null
    + + +

    Returns a String containing all headers separated by line breaks. +Does not throw errors if no headers are present the way its native +counterpart does.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/getallresponseheaders/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/getallresponseheaders/index.html new file mode 100644 index 000000000..52157471b --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/getallresponseheaders/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#getAllResponseHeaders + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Response#getAllResponseHeaders +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#getAllResponseHeaders() → String
    + + +

    Returns a String containing all headers separated by line breaks; throws +an error if no headers exist. This is just a wrapper around the +XmlHttpRequest method of the same name. Prefer it's shorter counterpart: +Ajax.Response#getAllHeaders.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/getheader/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/getheader/index.html new file mode 100644 index 000000000..d5dbb43fd --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/getheader/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#getHeader + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Response#getHeader +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#getHeader(name) → String | null
    + + +

    See Ajax.Request#getHeader.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/getresponseheader/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/getresponseheader/index.html new file mode 100644 index 000000000..8ddcb1868 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/getresponseheader/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#getResponseHeader + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Response#getResponseHeader +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#getResponseHeader(name) → String
    + + +

    Returns the value of the requested header if present; throws an error +otherwise. This is just a wrapper around the XmlHttpRequest method of +the same name. Prefer it's shorter counterpart: +Ajax.Response#getHeader.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/headerjson/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/headerjson/index.html new file mode 100644 index 000000000..6a9d17289 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/headerjson/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#headerJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#headerJSON +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#headerJSON → Object | Array | null
    + + +

    Auto-evaluated content of the X-JSON header if present; null otherwise. +This is useful to transfer small amounts of data.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/readystate/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/readystate/index.html new file mode 100644 index 000000000..f446c4831 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/readystate/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#readyState + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#readyState +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#readyState → Number
    + + +

    A Number corresponding to the request's current state.

    + +

    0 : "Uninitialized"
    +1 : "Loading"
    +2 : "Loaded"
    +3 : "Interactive"
    +4 : "Complete"

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/request/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/request/index.html new file mode 100644 index 000000000..81da96788 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/request/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#request +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#request → Ajax.Request | Ajax.Updater
    + + +

    The request object itself (an instance of Ajax.Request or +Ajax.Updater).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/responsejson/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/responsejson/index.html new file mode 100644 index 000000000..59a72b5cc --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/responsejson/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#responseJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#responseJSON +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#responseJSON → Object | Array | null
    + + +

    The JSON body of the response if the Content-type of the request is set +to application/json; null otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/responsetext/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/responsetext/index.html new file mode 100644 index 000000000..eedfac9eb --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/responsetext/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#responseText + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#responseText +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#responseText → String
    + + +

    The text body of the response.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/responsexml/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/responsexml/index.html new file mode 100644 index 000000000..85ddd700e --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/responsexml/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#responseXML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#responseXML +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#responseXML → document | null
    + + +

    The XML body of the response if the Content-type of the request is set +to application/xml; null otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/status/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/status/index.html new file mode 100644 index 000000000..263db4ed0 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/status/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#status + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#status +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#status → Number
    + + +

    The HTTP status code sent by the server.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/statustext/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/statustext/index.html new file mode 100644 index 000000000..420322dd9 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/statustext/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#statusText + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#statusText +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#statusText → String
    + + +

    The HTTP status text sent by the server.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/response/prototype/transport/index.html b/doc/1.7_rc1/ajax/ajax/response/prototype/transport/index.html new file mode 100644 index 000000000..33da09861 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/response/prototype/transport/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#transport + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#transport +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#transport → XmlHttpRequest
    + + +

    The native XmlHttpRequest object itself.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/updater/index.html b/doc/1.7_rc1/ajax/ajax/updater/index.html new file mode 100644 index 000000000..5f0730bb9 --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/updater/index.html @@ -0,0 +1,231 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Updater + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Ajax.Updater +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A class that performs an Ajax request and updates a container's contents +with the contents of the response.

    + +

    Ajax.Updater is a subclass of Ajax.Request built for a common +use-case.

    + +
    Example
    + +
    new Ajax.Updater('items', '/items', {
    +  parameters: { text: $F('text') }
    +});
    +
    +
    + +

    This example will make a request to the URL /items (with the given +parameters); it will then replace the contents of the element with the ID +of items with whatever response it receives.

    + +
    Callbacks
    + +

    Ajax.Updater supports all the callbacks listed in the Ajax. +Note that the onComplete callback will be invoked after the element +is updated.

    + +
    Additional options
    + +

    Ajax.Updater has some options of its own apart from the common options +described in the Ajax:

    + +
      +
    • evalScripts (Boolean; defaults to false): Whether <script> +elements in the response text should be evaluated.
    • +
    • insertion (String): By default, Element.update is used, meaning +the contents of the response will replace the entire contents of the +container. You may instead insert the response text without disrupting +existing contents. The insertion option takes one of four strings — +top, bottom, before, or after — and inserts the contents +of the response in the manner described by Element#insert.
    • +
    + +
    More About evalScripts
    + +

    If you use evalScripts: true, any inline <script> block will be +evaluated. This does not mean it will be evaluated in the global scope; +it won't, and that has important ramifications for your var and function +statements. Also note that only inline <script> blocks are supported; +external scripts are ignored. See String#evalScripts for the details.

    + +
    Single container, or success/failure split?
    + +

    The examples above all assume you're going to update the same container +whether your request succeeds or fails. Instead, you may want to update +only for successful requests, or update a different container on failed +requests.

    + +

    To achieve this, you can pass an object instead of a DOM element for the +container parameter. This object must have a success property whose +value identifies the container to be updated on successful requests.

    + +

    If you also provide it with a failure property, its value will be used as +the container for failed requests.

    + +

    In the following code, only successful requests get an update:

    + +
    new Ajax.Updater({ success: 'items' }, '/items', {
    +  parameters: { text: $F('text') },
    +  insertion: 'bottom'
    +});
    +
    +
    + +

    This next example assumes failed requests will deliver an error message as +response text — one that should be shown to the user in another area:

    + +
    new Ajax.Updater({ success: 'items', failure: 'notice' }, '/items',
    +  parameters: { text: $F('text') },
    +  insertion: 'bottom'
    +});
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/ajax/updater/new/index.html b/doc/1.7_rc1/ajax/ajax/updater/new/index.html new file mode 100644 index 000000000..4ea2a68fe --- /dev/null +++ b/doc/1.7_rc1/ajax/ajax/updater/new/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.7_rc1 API documentation | new Ajax.Updater + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Ajax.Updater +

    + + + + +
    +
    +
    +
    +
    +
    new(container, url[, options])
    +
      +
    • + container + (String | Element) + – The DOM element whose contents to update as a result of the Ajax request. Can be a DOM node or a string that identifies a node's ID. +
    • +
    • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
    • +
    • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
    • +
    + + +

    Creates a new Ajax.Updater.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/ajax/index.html b/doc/1.7_rc1/ajax/index.html new file mode 100644 index 000000000..e0d613204 --- /dev/null +++ b/doc/1.7_rc1/ajax/index.html @@ -0,0 +1,268 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax section + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +

    + section Ajax section +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Prototype's APIs around the XmlHttpRequest object.

    + +

    The Prototype framework enables you to deal with Ajax calls in a manner that +is both easy and compatible with all modern browsers.

    + +

    Actual requests are made by creating instances of Ajax.Request.

    + +
    Request headers
    + +

    The following headers are sent with all Ajax requests (and can be +overridden with the requestHeaders option described below):

    + +
      +
    • X-Requested-With is set to XMLHttpRequest.
    • +
    • X-Prototype-Version is set to Prototype's current version (e.g., +<%= PROTOTYPE_VERSION %>).
    • +
    • Accept is set to text/javascript, text/html, application/xml, +text/xml, * / *
    • +
    • Content-type is automatically determined based on the contentType +and encoding options.
    • +
    + +
    Ajax options
    + +

    All Ajax classes share a common set of options and callbacks. +Callbacks are called at various points in the life-cycle of a request, and +always feature the same list of arguments.

    + +
    Common options
    + +
      +
    • asynchronous (Boolean; default true): Determines whether +XMLHttpRequest is used asynchronously or not. Synchronous usage is +strongly discouraged — it halts all script execution for the +duration of the request and blocks the browser UI.
    • +
    • contentType (String; default application/x-www-form-urlencoded): +The Content-type header for your request. Change this header if you +want to send data in another format (like XML).
    • +
    • encoding (String; default UTF-8): The encoding for the contents +of your request. It is best left as-is, but should weird encoding issues +arise, you may have to tweak this.
    • +
    • method (String; default post): The HTTP method to use for the +request. The other common possibility is get. Abiding by Rails +conventions, Prototype also reacts to other HTTP verbs (such as put and +delete) by submitting via post and adding a extra _method parameter +with the originally-requested method.
    • +
    • parameters (String): The parameters for the request, which will be +encoded into the URL for a get method, or into the request body for the +other methods. This can be provided either as a URL-encoded string, a +Hash, or a plain Object.
    • +
    • postBody (String): Specific contents for the request body on a +post method. If it is not provided, the contents of the parameters +option will be used instead.
    • +
    • requestHeaders (Object): A set of key-value pairs, with properties +representing header names.
    • +
    • evalJS (Boolean | String; default true): Automatically evals +the content of Ajax.Response#responseText and populates +Ajax.Response#responseJSON with it if the Content-type returned by +the server is set to application/json. If the request doesn't obey +same-origin policy, the content is sanitized before evaluation. If you +need to force evalutation, pass 'force'. To prevent it altogether, pass +false.
    • +
    • sanitizeJSON (Boolean; default is false for same-origin requests, +true otherwise): Sanitizes the contents of +Ajax.Response#responseText before evaluating it.
    • +
    + +
    Common callbacks
    + +

    When used on individual instances, all callbacks (except onException) are +invoked with two parameters: the Ajax.Response object and the result of +evaluating the X-JSON response header, if any (can be null).

    + +

    For another way of describing their chronological order and which callbacks +are mutually exclusive, see Ajax.Request.

    + +
      +
    • onCreate: Triggered when the Ajax.Request object is initialized. +This is after the parameters and the URL have been processed, but +before opening the connection via the XHR object.
    • +
    • onUninitialized (Not guaranteed): Invoked just after the XHR object +is created.
    • +
    • onLoading (Not guaranteed): Triggered when the underlying XHR object +is being setup, and its connection opened.
    • +
    • onLoaded (Not guaranteed): Triggered once the underlying XHR object +is setup, the connection is open, and it is ready to send its actual +request.
    • +
    • onInteractive (Not guaranteed): Triggered whenever the requester +receives a part of the response (but not the final part), should it +be sent in several packets.
    • +
    • onSuccess: Invoked when a request completes and its status code is +undefined or belongs in the 2xy family. This is skipped if a +code-specific callback is defined (e.g., on200), and happens before +onComplete.
    • +
    • onFailure: Invoked when a request completes and its status code exists +but is not in the 2xy family. This is skipped if a code-specific +callback is defined (e.g. on403), and happens before onComplete.
    • +
    • onXYZ (with XYZ representing any HTTP status code): Invoked just +after the response is complete _if_ the status code is the exact code +used in the callback name. Prevents execution of onSuccess and +onFailure. Happens before onComplete.
    • +
    • onException: Triggered whenever an XHR error arises. Has a custom +signature: the first argument is the requester (i.e. an Ajax.Request +instance), and the second is the exception object.
    • +
    • onComplete: Triggered at the very end of a request's life-cycle, after +the request completes, status-specific callbacks are called, and possible +automatic behaviors are processed. Guaranteed to run regardless of what +happened during the request.
    • +
    +
    +
    + + + +
    +
    +

    Utilities

    +
    +
    + +
      +
    +
    +
    + + +
    +
    +

    Namespaces

    +
    +
    + + +
    +
    + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/abstract/eventobserver/index.html b/doc/1.7_rc1/dom/abstract/eventobserver/index.html new file mode 100644 index 000000000..5ec26e630 --- /dev/null +++ b/doc/1.7_rc1/dom/abstract/eventobserver/index.html @@ -0,0 +1,132 @@ + + + + + Prototype v1.7_rc1 API documentation | Abstract.EventObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Abstract.EventObserver +

    + + + + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/abstract/index.html b/doc/1.7_rc1/dom/abstract/index.html new file mode 100644 index 000000000..6a09d1e36 --- /dev/null +++ b/doc/1.7_rc1/dom/abstract/index.html @@ -0,0 +1,152 @@ + + + + + Prototype v1.7_rc1 API documentation | Abstract + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Abstract +

    + + + + + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Abstract.EventObserver

      + +
    • +
    • +

      Abstract.TimedObserver

      + +

      An abstract DOM element observer class, subclasses of which can be used to +periodically check a value and trigger a callback when the value has changed.

      +
    • +
    +
    +
    + + + + + + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/abstract/timedobserver/index.html b/doc/1.7_rc1/dom/abstract/timedobserver/index.html new file mode 100644 index 000000000..75c82e1f0 --- /dev/null +++ b/doc/1.7_rc1/dom/abstract/timedobserver/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Abstract.TimedObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Abstract.TimedObserver +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    An abstract DOM element observer class, subclasses of which can be used to +periodically check a value and trigger a callback when the value has changed.

    + +

    A TimedObserver object will try to check a value using the getValue() +instance method which must be defined by the subclass. There are two +out-of-the-box subclasses: +Form.Observer, which serializes a form and triggers when the result has +changed; and Form.Element.Observer, which triggers when the value of a +given form field changes.

    + +

    Using TimedObserver implementations is straightforward; simply instantiate +them with appropriate arguments. For example:

    + +
    new Form.Element.Observer(
    +  'myelement',
    +  0.2,  // 200 milliseconds
    +  function(el, value){
    +    alert('The form control has changed value to: ' + value)
    +  }
    +)
    +
    +
    + +

    Now that we have instantiated an object, it will check the value of the form +control every 0.2 seconds and alert us of any change. While it is useless to +alert the user of his own input (like in the example), we could be doing +something useful like updating a certain part of the UI or informing the +application on server of stuff happening (over Ajax).

    + +

    The callback function is always called with 2 arguments: the element given +when the observer instance was made and the actual value that has changed +and caused the callback to be triggered in the first place.

    + +
    Creating Your Own TimedObserver Implementations
    + +

    It's easy to create your own TimedObserver implementations: Simply subclass +TimedObserver and provide the getValue() method. For example, this is the +complete source code for Form.Element.Observer:

    + +
    Form.Element.Observer = Class.create(Abstract.TimedObserver, {
    +  getValue: function() {
    +    return Form.Element.getValue(this.element);
    +  }
    +});
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/abstract/timedobserver/new/index.html b/doc/1.7_rc1/dom/abstract/timedobserver/new/index.html new file mode 100644 index 000000000..b95639367 --- /dev/null +++ b/doc/1.7_rc1/dom/abstract/timedobserver/new/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.7_rc1 API documentation | new Abstract.TimedObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Abstract.TimedObserver +

    + + + + +
    +
    +
    +
    +
    +
    new(element, frequency, callback)
    +
      +
    • + element + (String | Element) + – The DOM element to watch. Can be an element instance or an ID. +
    • +
    • + frequency + (Number) + – The frequency, in seconds — e.g., 0.33 to check for changes every third of a second. +
    • +
    • + callback + (Function) + – The callback to trigger when the value changes. +
    • +
    + + +

    Initializes an Abstract.TimedObserver; used by subclasses.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/fire/index.html b/doc/1.7_rc1/dom/document/fire/index.html new file mode 100644 index 000000000..c74e45483 --- /dev/null +++ b/doc/1.7_rc1/dom/document/fire/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.7_rc1 API documentation | document.fire + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.fire +

    + + + + +
    +
    +
    +
    +
    +
    document.fire(eventName[, memo[, bubble = true]]) → Event
    +
      +
    • + memo + (?) + – Metadata for the event. Will be accessible through the event's memo property. +
    • +
    • + bubble + (Boolean) + – Whether the event will bubble. +
    • +
    + + +

    Fires a custom event of name eventName with document as the target.

    + +

    document.fire is the document-wide version of Element.fire.

    + +

    Custom events must include a colon (:) in their names.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/index.html b/doc/1.7_rc1/dom/document/index.html new file mode 100644 index 000000000..d22628ba3 --- /dev/null +++ b/doc/1.7_rc1/dom/document/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | document + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace document +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Prototype extends the built-in document object with several convenience +methods related to events.

    +
    +
    + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      document.viewport

      + +

      The document.viewport namespace contains methods that return information +about the viewport — the rectangle that represents the portion of a web +page within view. In other words, it's the browser window minus all chrome.

      +
    • +
    +
    +
    + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Class properties

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/loaded/index.html b/doc/1.7_rc1/dom/document/loaded/index.html new file mode 100644 index 000000000..317bd4773 --- /dev/null +++ b/doc/1.7_rc1/dom/document/loaded/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | document.loaded + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property document.loaded +

    + + + + +
    +
    +
    +
    +
    +
    document.loaded → Boolean
    + + +

    Whether the full DOM tree is ready for manipulation.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/observe/index.html b/doc/1.7_rc1/dom/document/observe/index.html new file mode 100644 index 000000000..2ff384fdd --- /dev/null +++ b/doc/1.7_rc1/dom/document/observe/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | document.observe + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.observe +

    + + + + +
    +
    +
    +
    +
    +
    document.observe(eventName, handler) → Element
    + + +

    Listens for the given event over the entire document. Can also be used +for listening to "dom:loaded" event.

    + +

    document.observe is the document-wide version of Element#observe. +Using document.observe is equivalent to +Event.observe(document, eventName, handler).

    + +
    The "dom:loaded" event
    + +

    One really useful event generated by Prototype that you might want to +observe on the document is "dom:loaded". On supporting browsers it +fires on DOMContentLoaded and on unsupporting browsers it simulates it +using smart workarounds. If you used window.onload before you might +want to switch to dom:loaded because it will fire immediately after +the HTML document is fully loaded, but before images on the page are +fully loaded. The load event on window only fires after all page +images are loaded, making it unsuitable for some initialization purposes +like hiding page elements (so they can be shown later).

    + +
    Example
    + +
    document.observe("dom:loaded", function() {
    +  // initially hide all containers for tab content
    +  $$('div.tabcontent').invoke('hide');
    +});
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/stopobserving/index.html b/doc/1.7_rc1/dom/document/stopobserving/index.html new file mode 100644 index 000000000..94aa33942 --- /dev/null +++ b/doc/1.7_rc1/dom/document/stopobserving/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | document.stopObserving + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.stopObserving +

    + + + + +
    +
    +
    +
    +
    +
    document.stopObserving([eventName[, handler]]) → Element
    + + +

    Unregisters an event handler from the document.

    + +

    document.stopObserving is the document-wide version of +Element.stopObserving.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/viewport/getdimensions/index.html b/doc/1.7_rc1/dom/document/viewport/getdimensions/index.html new file mode 100644 index 000000000..bf7e45693 --- /dev/null +++ b/doc/1.7_rc1/dom/document/viewport/getdimensions/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport.getDimensions + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.viewport.getDimensions +

    + + + + +
    +
    +
    +
    +
    +
    document.viewport.getDimensions() → Object
    + + +

    Returns an object containing viewport dimensions in the form +{ width: Number, height: Number }.

    + +

    The viewport is the subset of the browser window that a page occupies +— the "usable" space in a browser window.

    + +
    Example
    + +
    document.viewport.getDimensions();
    +//-> { width: 776, height: 580 }
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/viewport/getheight/index.html b/doc/1.7_rc1/dom/document/viewport/getheight/index.html new file mode 100644 index 000000000..b3eb9fbc0 --- /dev/null +++ b/doc/1.7_rc1/dom/document/viewport/getheight/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport.getHeight + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.viewport.getHeight +

    + + + + +
    +
    +
    +
    +
    +
    document.viewport.getHeight() → Number
    + + +

    Returns the height of the viewport.

    + +

    Equivalent to document.viewport.getDimensions().height.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/viewport/getscrolloffsets/index.html b/doc/1.7_rc1/dom/document/viewport/getscrolloffsets/index.html new file mode 100644 index 000000000..c57112f78 --- /dev/null +++ b/doc/1.7_rc1/dom/document/viewport/getscrolloffsets/index.html @@ -0,0 +1,157 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport.getScrollOffsets + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.viewport.getScrollOffsets +

    + + + + +
    +
    +
    +
    +
    +
    document.viewport.getScrollOffsets() → Array
    + + +

    Returns the viewport's horizontal and vertical scroll offsets.

    + +

    Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

    + +
    Examples
    + +
    document.viewport.getScrollOffsets();
    +//-> { left: 0, top: 0 }
    + window.scrollTo(0, 120);
    +document.viewport.getScrollOffsets();
    +//-> { left: 0, top: 120 }
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/viewport/getwidth/index.html b/doc/1.7_rc1/dom/document/viewport/getwidth/index.html new file mode 100644 index 000000000..4a1598990 --- /dev/null +++ b/doc/1.7_rc1/dom/document/viewport/getwidth/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport.getWidth + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.viewport.getWidth +

    + + + + +
    +
    +
    +
    +
    +
    document.viewport.getWidth() → Number
    + + +

    Returns the width of the viewport.

    + +

    Equivalent to calling document.viewport.getDimensions().width.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/document/viewport/index.html b/doc/1.7_rc1/dom/document/viewport/index.html new file mode 100644 index 000000000..9f7a4ca51 --- /dev/null +++ b/doc/1.7_rc1/dom/document/viewport/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace document.viewport +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    The document.viewport namespace contains methods that return information +about the viewport — the rectangle that represents the portion of a web +page within view. In other words, it's the browser window minus all chrome.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/dollar/index.html b/doc/1.7_rc1/dom/dollar/index.html new file mode 100644 index 000000000..c85e6a9f0 --- /dev/null +++ b/doc/1.7_rc1/dom/dollar/index.html @@ -0,0 +1,202 @@ + + + + + Prototype v1.7_rc1 API documentation | $ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $ +

    + + + + +
    +
    +
    +
    +
    +
    $(id) → Element
    $(id...) → [Element…]
    +
      +
    • + id + (String | Element) + – A DOM node or a string that references a node's ID. +
    • +
    + + +

    If provided with a string, returns the element in the document with +matching ID; otherwise returns the passed element.

    + +

    Takes in an arbitrary number of arguments. Returns one Element if +given one argument; otherwise returns an Array of Elements.

    + +

    All elements returned by the function are "extended" with Element +instance methods.

    + +
    More Information
    + +

    The $ function is the cornerstone of Prototype. Not only does it +provide a handy alias for document.getElementById, it also lets you pass +indifferently IDs (strings) or DOM node references to your functions:

    + +
    function foo(element) {
    +    element = $(element);
    +    //  rest of the function...
    +}
    +
    +
    + +

    Code written this way is flexible — you can pass it the ID of the element +or the element itself without any type sniffing.

    + +

    Invoking it with only one argument returns the Element, while invoking it +with multiple arguments returns an Array of Elements (and this +works recursively: if you're twisted, you could pass it an array +containing some arrays, and so forth). As this is dependent on +getElementById, W3C specs +apply: nonexistent IDs will yield null and IDs present multiple times in +the DOM will yield erratic results. *If you're assigning the same ID to +multiple elements, you're doing it wrong!*

    + +

    The function also extends every returned element with Element.extend +so you can use Prototype's DOM extensions on it. In the following code, +the two lines are equivalent. However, the second one feels significantly +more object-oriented:

    + +
    // Note quite OOP-like...
    +Element.hide('itemId');
    +// A cleaner feel, thanks to guaranted extension
    +$('itemId').hide();
    +
    +
    + +

    However, when using iterators, leveraging the $ function makes for +more elegant, more concise, and also more efficient code:

    + +
    ['item1', 'item2', 'item3'].each(Element.hide);
    +// The better way:
    +$('item1', 'item2', 'item3').invoke('hide');
    +
    +
    + +

    See How Prototype extends the DOM +for more info.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/dollardollar/index.html b/doc/1.7_rc1/dom/dollardollar/index.html new file mode 100644 index 000000000..f4abf0ae0 --- /dev/null +++ b/doc/1.7_rc1/dom/dollardollar/index.html @@ -0,0 +1,223 @@ + + + + + Prototype v1.7_rc1 API documentation | $$ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $$ +

    + + + + +
    +
    +
    +
    +
    +
    $$(cssRule...) → [Element…]
    + + +

    Takes an arbitrary number of CSS selectors (strings) and returns a document-order +array of extended DOM elements that match any of them.

    + +

    Sometimes the usual tools from your DOM arsenal -- document.getElementById encapsulated +by $, getElementsByTagName and even Prototype's very own getElementsByClassName +extensions -- just aren't enough to quickly find elements or collections of elements. +If you know the DOM tree structure, you can simply resort to CSS selectors to get +the job done.

    + +
    Quick examples
    + +
    $$('div');
    +// -> all DIVs in the document. Same as document.getElementsByTagName('div').
    +// Nice addition, the elements you're getting back are already extended!
    + $$('#contents');
    +// -> same as $('contents'), only it returns an array anyway (even though IDs must
    +// be unique within a document).
    + $$('li.faux');
    +// -> all LI elements with class 'faux'
    +
    +
    + +

    The $$ function searches the entire document. For selector queries on more specific +sections of a document, use Element.select.

    + +
    Supported CSS syntax
    + +

    The $$ function does not rely on the browser's internal CSS parsing capabilities +(otherwise, we'd be in cross-browser trouble...), and therefore offers a consistent +set of selectors across all supported browsers.

    + +
    Supported in v1.5.0
    + +
      +
    • Type selector: tag names, as in div.
    • +
    • Descendant selector: the space(s) between other selectors, as in #a li.
    • +
    • Attribute selectors: the full CSS 2.1 set of [attr], [attr=value], [attr~=value] +and [attr|=value]. It also supports [attr!=value]. If the value you're matching +against includes a space, be sure to enclose the value in quotation marks ([title="Hello World!"]).
    • +
    • Class selector: CSS class names, as in .highlighted or .example.wrong.
    • +
    • ID selector: as in #item1.
    • +
    + +
    Supported from v1.5.1
    + +

    Virtually all of CSS3 +is supported, with the exception of pseudo-elements (like ::first-letter) and some +pseudo-classes (like :hover). Some examples of new selectors that can be used in 1.5.1:

    + +
      +
    • Child selector: selects immediate descendants, as in #a > li.
    • +
    • Attribute selectors: all attribute operators are supported, including ~= (matches +part of a space-delimited attribute value, like rel or class); ^= (matches the +beginning of a value); $= (matches the end of a value); and *= (matches any part +of the value).
    • +
    • The :not pseudo-class, as in #a *:not(li) (matches all descendants of #a that +aren't LIs).
    • +
    • All the :nth, :first, and :last pseudo-classes. Examples include tr:nth-child(even) +(all even table rows), li:first-child (the first item in any list), or p:nth-last-of-type(3) +(the third-to-last paragraph on the page).
    • +
    • The :empty pseudo-class (for selecting elements without children or text content).
    • +
    • The :enabled, :disabled, and :checked pseudo-classes (for use with form controls).
    • +
    + +
    Examples
    + +
    $$('#contents a[rel]');
    +// -> all links inside the element of ID "contents" with a rel attribute
    + $$('a[href="#"]');
    +// -> all links with a href attribute of value "#" (eyeew!)
    + $$('#navbar a', '#sidebar a');
    +// -> all links within the elements of ID "navbar" or "sidebar"
    +
    +
    + +

    With version 1.5.1 and above you can do various types of advanced selectors:

    + +
    $$('a:not([rel~=nofollow])');
    +// -> all links, excluding those whose rel attribute contains the word "nofollow"
    + $$('table tbody > tr:nth-child(even)');
    +// -> all even rows within all table bodies
    + $$('div:empty');
    +// -> all DIVs without content (i.e., whitespace-only)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/dollarf/index.html b/doc/1.7_rc1/dom/dollarf/index.html new file mode 100644 index 000000000..b906323c6 --- /dev/null +++ b/doc/1.7_rc1/dom/dollarf/index.html @@ -0,0 +1,140 @@ + + + + + Prototype v1.7_rc1 API documentation | $F + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $F +

    + + + + +
    +
    +
    +
    +
    +
    $F(element) → String | Array
    + + +

    Returns the value of a form control. This is a convenience alias of +Form.Element.getValue. Refer to it for full details.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/absolutize/index.html b/doc/1.7_rc1/dom/element/absolutize/index.html new file mode 100644 index 000000000..1649cb2d7 --- /dev/null +++ b/doc/1.7_rc1/dom/element/absolutize/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.absolutize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.absolutize +

    + + + + +
    +
    +
    +
    +
    +
    Element.absolutize(element) → Element
    + + +

    Turns element into an absolutely-positioned element without +changing its position in the page layout.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/addclassname/index.html b/doc/1.7_rc1/dom/element/addclassname/index.html new file mode 100644 index 000000000..0ad07f90a --- /dev/null +++ b/doc/1.7_rc1/dom/element/addclassname/index.html @@ -0,0 +1,322 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.addClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.addClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element.addClassName(element, className) → Element
    +
      +
    • + className + (String) + – The class name to add. +
    • +
    + + +

    Adds the given CSS class to element.

    + +
    Example
    + +

    Assuming this HTML:

    + +
    <div id="mutsu" class="apple fruit"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').className;
    +// -> 'apple fruit'
    +$('mutsu').addClassName('food');
    +$('mutsu').className;
    +// -> 'apple fruit food'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/addmethods/index.html b/doc/1.7_rc1/dom/element/addmethods/index.html new file mode 100644 index 000000000..96a3e5bbf --- /dev/null +++ b/doc/1.7_rc1/dom/element/addmethods/index.html @@ -0,0 +1,438 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.addMethods + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.addMethods +

    + + + + +
    +
    +
    +
    +
    +
    Element.addMethods(methods) → undefined
    Element.addMethods(tagName, methods) → undefined
    +
      +
    • + tagName + (String) + – (Optional) The name of the HTML tag for which the methods should be available; if not given, all HTML elements will have the new methods. +
    • +
    • + methods + (Object) + – A hash of methods to add. +
    • +
    + + +

    Element.addMethods makes it possible to mix your own methods into the +Element object and extended element instances (all of them, or only ones +with the given HTML tag if you specify tagName).

    + +

    You define the methods in a hash that you provide to Element.addMethods. +Here's an example adding two methods:

    + +
    Element.addMethods({
    +   // myOwnMethod: Do something cool with the element
    +  myOwnMethod: function(element) {
    +    if (!(element = $(element))) return;
    +    // ...do smething with 'element'...
    +    return element;
    +  },
    +   // wrap: Wrap the element in a new element using the given tag
    +  wrap: function(element, tagName) {
    +    var wrapper;
    +    if (!(element = $(element))) return;
    +    wrapper = new Element(tagName);
    +    element.parentNode.replaceChild(wrapper, element);
    +    wrapper.appendChild(element);
    +    return wrapper;
    +  }
    + });
    +
    +
    + +

    Once added, those can be used either via Element:

    + +
    // Wrap the element with the ID 'foo' in a div
    +Element.wrap('foo', 'div');
    +
    +
    + +

    ...or as instance methods of extended elements:

    + +
    // Wrap the element with the ID 'foo' in a div
    +$('foo').wrap('div');
    +
    +
    + +

    Note the following requirements and conventions for methods added to +Element:

    + +
      +
    • The first argument is always an element or ID, by convention this +argument is called element.
    • +
    • The method passes the element argument through $ and typically +returns if the result is undefined.
    • +
    • Barring a good reason to return something else, the method returns the +extended element to enable chaining.
    • +
    + +

    Our myOwnMethod method above returns the element because it doesn't have +a good reason to return anything else. Our wrap method returns the +wrapper, because that makes more sense for that method.

    + +
    Extending only specific elements
    + +

    If you call Element.addMethods with two arguments, it will apply the +methods only to elements with the given HTML tag:

    + +
    Element.addMethods('DIV', my_div_methods);
    +// the given methods are now available on DIV elements, but not others
    +
    +
    + +

    You can also pass an Array of tag names as the first argument:

    + +
    Element.addMethods(['DIV', 'SPAN'], my_additional_methods);
    +// DIV and SPAN now both have the given methods
    +
    +
    + +

    (Tag names in the first argument are not case sensitive.)

    + +

    Note: Element.addMethods has built-in security which prevents you from +overriding native element methods or properties (like getAttribute or +innerHTML), but nothing prevents you from overriding one of Prototype's +methods. Prototype uses a lot of its methods internally; overriding its +methods is best avoided or at least done only with great care.

    + +
    Example 1
    + +

    Our wrap method earlier was a complete example. For instance, given this +paragraph:

    + +
    <p id="first">Some content...</p>
    +
    +
    + +

    ...we might wrap it in a div:

    + +
    $('first').wrap('div');
    +
    +
    + +

    ...or perhaps wrap it and apply some style to the div as well:

    + +
    $('first').wrap('div').setStyle({
    +  backgroundImage: 'url(images/rounded-corner-top-left.png) top left'
    +});
    +
    +
    + +
    Example 2
    + +

    We can add a method to elements that makes it a bit easier to update them +via Ajax.Updater:

    + +
    Element.addMethods({
    +  ajaxUpdate: function(element, url, options) {
    +    if (!(element = $(element))) return;
    +    element.update('<img src="/images/spinner.gif" alt="Loading...">');
    +    options = options || {};
    +    options.onFailure = options.onFailure || defaultFailureHandler.curry(element);
    +    new Ajax.Updater(element, url, options);
    +    return element;
    +  }
    +});
    +
    +
    + +

    Now we can update an element via an Ajax call much more concisely than +before:

    + +
    $('foo').ajaxUpdate('/new/content');
    +
    +
    + +

    That will use Ajax.Updater to load new content into the 'foo' element, +showing a spinner while the call is in progress. It even applies a default +failure handler (since we didn't supply one).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/adjacent/index.html b/doc/1.7_rc1/dom/element/adjacent/index.html new file mode 100644 index 000000000..505374ace --- /dev/null +++ b/doc/1.7_rc1/dom/element/adjacent/index.html @@ -0,0 +1,331 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.adjacent + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.adjacent +

    + + + + +
    +
    +
    +
    +
    +
    Element.adjacent(element, selector...) → [Element…]
    +
      +
    • + selector + (String) + – A CSS selector. +
    • +
    + + +

    Finds all siblings of the current element that match the given +selector(s). If you provide multiple selectors, siblings matching any +of the selectors are included. If a sibling matches multiple selectors, +it is only included once. The order of the returned array is not defined.

    + +
    Example
    + +

    Assuming this list:

    + +
    <ul id="cities">
    +  <li class="us" id="nyc">New York</li>
    +  <li class="uk" id="lon">London</li>
    +  <li class="us" id="chi">Chicago</li>
    +  <li class="jp" id="tok">Tokyo</li>
    +  <li class="us" id="la">Los Angeles</li>
    +  <li class="us" id="aus">Austin</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('nyc').adjacent('li.us');
    +// -> [li#chi, li#la, li#aus]
    +$('nyc').adjacent('li.uk', 'li.jp');
    +// -> [li#lon, li#tok]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/ancestors/index.html b/doc/1.7_rc1/dom/element/ancestors/index.html new file mode 100644 index 000000000..36b7a02b5 --- /dev/null +++ b/doc/1.7_rc1/dom/element/ancestors/index.html @@ -0,0 +1,327 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.ancestors + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.ancestors +

    + + + + +
    +
    +
    +
    +
    +
    Element.ancestors(element) → [Element…]
    + + +

    Collects all of element's ancestor elements and returns them as an +array of extended elements.

    + +

    The returned array's first element is element's direct ancestor (its +parentNode), the second one is its grandparent, and so on until the +<html> element is reached. <html> will always be the last member of +the array. Calling ancestors on the <html> element will return an +empty array.

    + +
    Example
    + +

    Assuming:

    + +
    <html>
    +[...]
    +  <body>
    +    <div id="father">
    +      <div id="kid">
    +      </div>
    +    </div>
    +  </body>
    +</html>
    +
    +
    + +

    Then:

    + +
    $('kid').ancestors();
    +// -> [div#father, body, html]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/childelements/index.html b/doc/1.7_rc1/dom/element/childelements/index.html new file mode 100644 index 000000000..3146d279e --- /dev/null +++ b/doc/1.7_rc1/dom/element/childelements/index.html @@ -0,0 +1,328 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.childElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.childElements +

    + + + + +
    +
    +
    +
    +
    +
    Element.childElements(element) → [Element…]
    + + +

    Collects all of the element's children and returns them as an array of +Element.extended elements, in document order. The first +entry in the array is the topmost child of element, the next is the +child after that, etc.

    + +

    Like all of Prototype's DOM traversal methods, Element.childElements +ignores text nodes and returns element nodes only.

    + +
    Example
    + +

    Assuming:

    + +
    <div id="australopithecus">
    +  Some text in a text node
    +  <div id="homo-erectus">
    +    <div id="homo-neanderthalensis"></div>
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('australopithecus').childElements();
    +// -> [div#homo-erectus]
    + $('homo-erectus').childElements();
    +// -> [div#homo-neanderthalensis, div#homo-sapiens]
    + $('homo-sapiens').childElements();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/classnames/index.html b/doc/1.7_rc1/dom/element/classnames/index.html new file mode 100644 index 000000000..1b68d0fbe --- /dev/null +++ b/doc/1.7_rc1/dom/element/classnames/index.html @@ -0,0 +1,303 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.classNames + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Element.classNames +

    + + + + +
    +
    +
    +
    +
    +
    Element.classNames(element) → [String…]
    + + +

    Returns a new instance of Element.ClassNames, an Enumerable +object used to read and write CSS class names of element.

    + +

    Deprecated, please see Element.addClassName, +Element.removeClassName, and Element.hasClassName. If you want +an array of classnames, you can use $w(element.className).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/cleanwhitespace/index.html b/doc/1.7_rc1/dom/element/cleanwhitespace/index.html new file mode 100644 index 000000000..a181c749f --- /dev/null +++ b/doc/1.7_rc1/dom/element/cleanwhitespace/index.html @@ -0,0 +1,339 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.cleanWhitespace + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.cleanWhitespace +

    + + + + +
    +
    +
    +
    +
    +
    Element.cleanWhitespace(element) → Element
    + + +

    Removes all of element's child text nodes that contain only +whitespace. Returns element.

    + +

    This can be very useful when using standard properties like nextSibling, +previousSibling, firstChild or lastChild to walk the DOM. Usually +you'd only do that if you are interested in all of the DOM nodes, not +just Elements (since if you just need to traverse the Elements in the +DOM tree, you can use Element.up, Element.down, +Element.next, and Element.previous instead).

    + +

    Example

    + +

    Consider the following HTML snippet:

    + +
    <ul id="apples">
    +  <li>Mutsu</li>
    +  <li>McIntosh</li>
    +  <li>Ida Red</li>
    +</ul>
    +
    +
    + +

    Let's grab what we think is the first list item using the raw DOM +method:

    + +
    var element = $('apples');
    +element.firstChild.innerHTML;
    +// -> undefined
    +
    +
    + +

    It's undefined because the firstChild of the apples element is a +text node containing the whitespace after the end of the ul and before +the first li.

    + +

    If we remove the useless whitespace, then firstChild works as expected:

    + +
    var element = $('apples');
    +element.cleanWhitespace();
    +element.firstChild.innerHTML;
    +// -> 'Mutsu'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/clone/index.html b/doc/1.7_rc1/dom/element/clone/index.html new file mode 100644 index 000000000..8b0526981 --- /dev/null +++ b/doc/1.7_rc1/dom/element/clone/index.html @@ -0,0 +1,307 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.clone +

    + + + + +
    +
    +
    +
    +
    +
    Element.clone(element, deep) → Element
    +
      +
    • + deep + (Boolean) + – Whether to clone element's descendants as well. +
    • +
    + + +

    Returns a duplicate of element.

    + +

    A wrapper around DOM Level 2 Node#cloneNode, Element.clone cleans up +any expando properties defined by Prototype.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/cloneposition/index.html b/doc/1.7_rc1/dom/element/cloneposition/index.html new file mode 100644 index 000000000..1718d92ed --- /dev/null +++ b/doc/1.7_rc1/dom/element/cloneposition/index.html @@ -0,0 +1,359 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.clonePosition + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.clonePosition +

    + + + + +
    +
    +
    +
    +
    +
    Element.clonePosition(element, source[, options]) → Element
    +
      +
    • + source + (Element | String) + – The source element (or its ID). +
    • +
    • + options + (Object) + – The position fields to clone. +
    • +
    + + +

    Clones the position and/or dimensions of source onto the element as +defined by options, with an optional offset for the left and top +properties.

    + +

    Note that the element will be positioned exactly like source whether or +not it is part of the same CSS containing +block.

    + +
    Options
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDefaultDescription
    setLefttrueClones source's left CSS property onto element.
    setToptrueClones source's top CSS property onto element.
    setWidthtrueClones source's width onto element.
    setHeighttrueClones source's width onto element.
    offsetLeft0Number by which to offset element's left CSS property.
    offsetTop0Number by which to offset element's top CSS property.
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/cumulativeoffset/index.html b/doc/1.7_rc1/dom/element/cumulativeoffset/index.html new file mode 100644 index 000000000..a0014ec14 --- /dev/null +++ b/doc/1.7_rc1/dom/element/cumulativeoffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.cumulativeOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.cumulativeOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element.cumulativeOffset(element) → Element.Offset
    + + +

    Returns the offsets of element from the top left corner of the +document.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/cumulativescrolloffset/index.html b/doc/1.7_rc1/dom/element/cumulativescrolloffset/index.html new file mode 100644 index 000000000..51553d52e --- /dev/null +++ b/doc/1.7_rc1/dom/element/cumulativescrolloffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.cumulativeScrollOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.cumulativeScrollOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element.cumulativeScrollOffset(element) → Element.Offset
    + + +

    Calculates the cumulative scroll offset of an element in nested +scrolling containers.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/descendantof/index.html b/doc/1.7_rc1/dom/element/descendantof/index.html new file mode 100644 index 000000000..efeb40118 --- /dev/null +++ b/doc/1.7_rc1/dom/element/descendantof/index.html @@ -0,0 +1,325 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.descendantOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.descendantOf +

    + + + + +
    +
    +
    +
    +
    +
    Element.descendantOf(element, ancestor) → Boolean
    +
      +
    • + ancestor + (Element | String) + – The element to check against (or its ID). +
    • +
    + + +

    Checks if element is a descendant of ancestor.

    + +
    Example
    + +

    Assuming:

    + +
    <div id="australopithecus">
    +  <div id="homo-erectus">
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('homo-sapiens').descendantOf('australopithecus');
    +// -> true
    + $('homo-erectus').descendantOf('homo-sapiens');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/descendants/index.html b/doc/1.7_rc1/dom/element/descendants/index.html new file mode 100644 index 000000000..136a1e956 --- /dev/null +++ b/doc/1.7_rc1/dom/element/descendants/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.descendants + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.descendants +

    + + + + +
    +
    +
    +
    +
    +
    Element.descendants(element) → [Element…]
    + + +

    Collects all of the element's descendants (its children, their children, +etc.) and returns them as an array of extended elements. As with all of +Prototype's DOM traversal methods, only Elements are returned, other +nodes (text nodes, etc.) are skipped.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/down/index.html b/doc/1.7_rc1/dom/element/down/index.html new file mode 100644 index 000000000..a0cc0d7f8 --- /dev/null +++ b/doc/1.7_rc1/dom/element/down/index.html @@ -0,0 +1,409 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.down + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.down +

    + + + + +
    +
    +
    +
    +
    +
    Element.down(element[, expression[, index = 0]]) → Element
    Element.down(element[, index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first descendant (or the Nth descendant, if index +is specified) that matches expression. If no expression is +provided, all descendants are considered. If no descendant matches these +criteria, undefined is returned.

    + +
    More information
    + +

    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 +(see Element.extend) allowing chaining:

    + +
    $(element).down(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's first descendant is returned (this +is similar to calling firstChild except Element.down returns an +extended element.

    + +

    If index is defined, element's corresponding descendant is returned. +(This is equivalent to selecting an element from the array of elements +returned by the method Element.descendants.) Note that the first +element has an index of 0.

    + +

    If expression is defined, Element.down will return the first +descendant that matches it. This is a great way to grab the first item in +a list for example (just pass in 'li' as the method's first argument).

    + +

    If both expression and index are defined, Element.down will collect +all the descendants matching the given CSS expression and will return the +one at the specified index.

    + +

    In all of the above cases, if no descendant is found, undefined +will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <ul>
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first descendant of "#fruites":

    + +
    $('fruits').down();
    +// or:
    +$('fruits').down(0);
    +// -> li#apples
    +
    +
    + +

    Get the third descendant of "#fruits":

    + +
    $('fruits').down(3);
    +// -> li#golden-delicious
    +
    +
    + +

    Get the first descendant of "#apples" with the node name "li":

    + +
    $('apples').down('li');
    +// -> li#golden-delicious
    +
    +
    + +

    Get the first descendant of "#apples" with the node name "li" and the +class name "yummy":

    + +
    $('apples').down('li.yummy');
    +// -> li#mutsu
    +
    +
    + +

    Get the second descendant of "#fruits" with the class name "yummy":

    + +
    $('fruits').down('.yummy', 1);
    +// -> li#mcintosh
    +
    +
    + +

    Try to get the ninety-ninth descendant of "#fruits":

    + +
    $('fruits').down(99);
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/empty/index.html b/doc/1.7_rc1/dom/element/empty/index.html new file mode 100644 index 000000000..8511d201f --- /dev/null +++ b/doc/1.7_rc1/dom/element/empty/index.html @@ -0,0 +1,308 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.empty + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.empty +

    + + + + +
    +
    +
    +
    +
    +
    Element.empty(element) → Element
    + + +

    Tests whether element is empty (i.e., contains only whitespace).

    + +
    Examples
    + +
    <div id="wallet">     </div>
    +<div id="cart">full!</div>
    + $('wallet').empty();
    +// -> true
    + $('cart').empty();
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/extend/index.html b/doc/1.7_rc1/dom/element/extend/index.html new file mode 100644 index 000000000..f3801d549 --- /dev/null +++ b/doc/1.7_rc1/dom/element/extend/index.html @@ -0,0 +1,313 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.extend +

    + + + + +
    +
    +
    +
    +
    +
    Element.extend(element) → Element
    + + +

    Extends the given element instance with all of the Prototype goodness and +syntactic sugar, as well as any extensions added via Element.addMethods. +(If the element instance was already extended, this is a no-op.)

    + +

    You only need to use Element.extend on element instances you've acquired +directly from the DOM; all Prototype methods that return element +instances (such as $, Element.down, etc.) will pre-extend the +element before returning it.

    + +

    Check out "How Prototype extends the +DOM" for more about element +extensions.

    + +
    Details
    + +

    Specifically, Element.extend extends the given instance with the methods +contained in Element.Methods and Element.Methods.Simulated. If element +is an input, textarea, or select element, it will also be extended +with the methods from Form.Element.Methods. If it is a form element, it +will also be extended with the methods from Form.Methods.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/fire/index.html b/doc/1.7_rc1/dom/element/fire/index.html new file mode 100644 index 000000000..b7c960b1e --- /dev/null +++ b/doc/1.7_rc1/dom/element/fire/index.html @@ -0,0 +1,336 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.fire + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.fire +

    + + + + +
    +
    +
    +
    +
    +
    Element.fire(element, eventName[, memo[, bubble = true]]) → Event
    + + +

    See Event.fire.

    + +

    Fires a custom event with the current element as its target.

    + +

    Element.fire creates a custom event with the given name, then triggers +it on the given element. The custom event has all the same properties +and methods of native events. Like a native event, it will bubble up +through the DOM unless its propagation is explicitly stopped.

    + +

    The optional second argument will be assigned to the memo property of +the event object so that it can be read by event handlers.

    + +

    Custom events are dispatched synchronously: Element.fire waits until +the event finishes its life cycle, then returns the event itself.

    + +
    Note
    + +

    Element.fire does not support firing native events. All custom event +names must be namespaced (using a colon). This is to avoid custom +event names conflicting with non-standard native DOM events such as +mousewheel and DOMMouseScroll.

    + +
    Examples
    + +
    document.observe("widget:frobbed", function(event) {
    +  console.log("Element with ID (" + event.target.id +
    +   ") frobbed widget #" + event.memo.widgetNumber + ".");
    +});
    + var someNode = $('foo');
    +someNode.fire("widget:frobbed", { widgetNumber: 19 });
    + //-> "Element with ID (foo) frobbed widget #19."
    +
    +
    + +
    Tip
    + +

    Events that have been stopped with Event.stop will have a boolean +stopped property set to true. Since Element.fire returns the custom +event, you can inspect this property to determine whether the event was +stopped.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/firstdescendant/index.html b/doc/1.7_rc1/dom/element/firstdescendant/index.html new file mode 100644 index 000000000..d8db0d3f1 --- /dev/null +++ b/doc/1.7_rc1/dom/element/firstdescendant/index.html @@ -0,0 +1,324 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.firstDescendant + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.firstDescendant +

    + + + + +
    +
    +
    +
    +
    +
    Element.firstDescendant(element) → Element
    + + +

    Returns the first child that is an element.

    + +

    This is opposed to the firstChild DOM property, which will return +any node, including text nodes and comment nodes.

    + +
    Examples
    + +
    <div id="australopithecus">
    +  <div id="homo-erectus"><!-- Latin is super -->
    +    <div id="homo-neanderthalensis"></div>
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('australopithecus').firstDescendant();
    +// -> div#homo-herectus
    + // the DOM property returns any first node
    +$('homo-herectus').firstChild;
    +// -> comment node "Latin is super"
    + // this is what we want!
    +$('homo-herectus').firstDescendant();
    +// -> div#homo-neanderthalensis
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getdimensions/index.html b/doc/1.7_rc1/dom/element/getdimensions/index.html new file mode 100644 index 000000000..2010b1dac --- /dev/null +++ b/doc/1.7_rc1/dom/element/getdimensions/index.html @@ -0,0 +1,326 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getDimensions + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getDimensions +

    + + + + +
    +
    +
    +
    +
    +
    Element.getDimensions(element) → Object
    + + +

    Finds the computed width and height of element and returns them as +key/value pairs of an object.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    In order to avoid calling the method twice, you should consider caching +the values returned in a variable as shown below. If you only need +element's width or height, consider using Element.getWidth or +Element.getHeight instead.

    + +

    Note that all values are returned as numbers only although they are +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    var dimensions = $('rectangle').getDimensions();
    +// -> {width: 200, height: 100}
    + dimensions.width;
    +// -> 200
    + dimensions.height;
    +// -> 100
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getelementsbyselector/index.html b/doc/1.7_rc1/dom/element/getelementsbyselector/index.html new file mode 100644 index 000000000..f243b690d --- /dev/null +++ b/doc/1.7_rc1/dom/element/getelementsbyselector/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getElementsBySelector + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getElementsBySelector +

    + + + + +
    +
    +
    +
    +
    +
    Element.getElementsBySelector(element, selector) → [Element…]
    + + + + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getheight/index.html b/doc/1.7_rc1/dom/element/getheight/index.html new file mode 100644 index 000000000..3a6cac756 --- /dev/null +++ b/doc/1.7_rc1/dom/element/getheight/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getHeight + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getHeight +

    + + + + +
    +
    +
    +
    +
    +
    Element.getHeight(element) → Number
    + + +

    Returns the height of element.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    For performance reasons, if you need to query both width and height of +element, you should consider using Element.getDimensions instead.

    + +

    Note that the value returned is a number only although it is +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    $('rectangle').getHeight();
    +// -> 100
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getlayout/index.html b/doc/1.7_rc1/dom/element/getlayout/index.html new file mode 100644 index 000000000..82d65ba7f --- /dev/null +++ b/doc/1.7_rc1/dom/element/getlayout/index.html @@ -0,0 +1,305 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getLayout + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getLayout +

    + + + + +
    +
    +
    +
    +
    +
    Element.getLayout(element, preCompute) → Element.Layout
    + + +

    Returns an instance of Element.Layout for measuring an element's +dimensions.

    + +

    Note that this method returns a new Element.Layout object each time +it's called. If you want to take advantage of measurement caching, +retain a reference to one Element.Layout object, rather than calling +Element.getLayout whenever you need a measurement. You should call +Element.getLayout again only when the values in an existing +Element.Layout object have become outdated.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getoffsetparent/index.html b/doc/1.7_rc1/dom/element/getoffsetparent/index.html new file mode 100644 index 000000000..f29b8d74c --- /dev/null +++ b/doc/1.7_rc1/dom/element/getoffsetparent/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getOffsetParent + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getOffsetParent +

    + + + + +
    +
    +
    +
    +
    +
    Element.getOffsetParent(element) → Element
    + + +

    Returns element's closest positioned ancestor. If none is found, the +body element is returned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getopacity/index.html b/doc/1.7_rc1/dom/element/getopacity/index.html new file mode 100644 index 000000000..0423c01c0 --- /dev/null +++ b/doc/1.7_rc1/dom/element/getopacity/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getOpacity + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getOpacity +

    + + + + +
    +
    +
    +
    +
    +
    Element.getOpacity(element) → String | null
    + + +

    Returns the opacity of the element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getstorage/index.html b/doc/1.7_rc1/dom/element/getstorage/index.html new file mode 100644 index 000000000..fda1f05dd --- /dev/null +++ b/doc/1.7_rc1/dom/element/getstorage/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getStorage + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getStorage +

    + + + + +
    +
    +
    +
    +
    +
    Element.getStorage(element) → Hash
    + + +

    Returns the Hash object that stores custom metadata for this element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getstyle/index.html b/doc/1.7_rc1/dom/element/getstyle/index.html new file mode 100644 index 000000000..509ff4911 --- /dev/null +++ b/doc/1.7_rc1/dom/element/getstyle/index.html @@ -0,0 +1,354 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getStyle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getStyle +

    + + + + +
    +
    +
    +
    +
    +
    Element.getStyle(element, style) → String | null
    +
      +
    • + style + (String) + – The property name to be retrieved. +
    • +
    + + +

    Returns the given CSS property value of element. The property can be +specified in either its CSS form (font-size) or its camelized form +(fontSize).

    + +

    This method looks up the CSS property of an element whether it was +applied inline or in a stylesheet. It works around browser inconsistencies +regarding float, opacity, which returns a value between 0 +(fully transparent) and 1 (fully opaque), position properties +(left, top, right and bottom) and when getting the dimensions +(width or height) of hidden elements.

    + +
    Examples
    + +
    $(element).getStyle('font-size');
    +// equivalent:
    + $(element).getStyle('fontSize');
    +// -> '12px'
    +
    +
    + +
    Notes
    + +

    Internet Explorer returns literal values while other browsers return +computed values.

    + +

    Consider the following HTML snippet:

    + +
    <style>
    +  #test {
    +    font-size: 12px;
    +    margin-left: 1em;
    +  }
    +</style>
    +<div id="test"></div>
    +
    +
    + +

    Then:

    + +
    $('test').getStyle('margin-left');
    +// -> '1em' in Internet Explorer,
    +// -> '12px' elsewhere.
    +
    +
    + +

    Safari returns null for any non-inline property if the element is +hidden (has display set to 'none').

    + +

    Not all CSS shorthand properties are supported. You may only use the CSS +properties described in the +Document Object Model (DOM) Level 2 Style Specification.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/getwidth/index.html b/doc/1.7_rc1/dom/element/getwidth/index.html new file mode 100644 index 000000000..b82f9ccbb --- /dev/null +++ b/doc/1.7_rc1/dom/element/getwidth/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getWidth + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getWidth +

    + + + + +
    +
    +
    +
    +
    +
    Element.getWidth(element) → Number
    + + +

    Returns the width of element.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    For performance reasons, if you need to query both width and height of +element, you should consider using Element.getDimensions instead.

    + +

    Note that the value returned is a number only although it is +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    $('rectangle').getWidth();
    +// -> 200
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/hasattribute/index.html b/doc/1.7_rc1/dom/element/hasattribute/index.html new file mode 100644 index 000000000..6540feb38 --- /dev/null +++ b/doc/1.7_rc1/dom/element/hasattribute/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.hasAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.hasAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element.hasAttribute(element, attribute) → Boolean
    + + +

    Simulates the standard compliant DOM method +hasAttribute +for browsers missing it (Internet Explorer 6 and 7).

    + +
    Example
    + +
    <a id="link" href="http://prototypejs.org">Prototype</a>
    +
    +
    + +

    Then:

    + +
    $('link').hasAttribute('href');
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/hasclassname/index.html b/doc/1.7_rc1/dom/element/hasclassname/index.html new file mode 100644 index 000000000..623620687 --- /dev/null +++ b/doc/1.7_rc1/dom/element/hasclassname/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.hasClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.hasClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element.hasClassName(element, className) → Boolean
    + + +

    Checks for the presence of CSS class className on element.

    + +
    Examples
    + +
    <div id="mutsu" class="apple fruit food"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').hasClassName('fruit');
    +// -> true
    + $('mutsu').hasClassName('vegetable');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/hide/index.html b/doc/1.7_rc1/dom/element/hide/index.html new file mode 100644 index 000000000..49fa9da21 --- /dev/null +++ b/doc/1.7_rc1/dom/element/hide/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.hide + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.hide +

    + + + + +
    +
    +
    +
    +
    +
    Element.hide(element) → Element
    + + +

    Sets display: none on element. Returns element.

    + +
    Examples
    + +

    Hide a single element:

    + +
    <div id="error-message"></div>
    + $('error-message').hide();
    +// -> Element (and hides div#error-message)
    +
    +
    + +

    Hide multiple elements using Enumerable#each:

    + +
    ['content', 'navigation', 'footer'].each(Element.hide);
    +// -> ['content', 'navigation', 'footer']
    +
    +
    + +

    Hide multiple elements using Enumerable#invoke:

    + +
    $('content', 'navigation', 'footer').invoke('hide');
    +// -> [Element, Element, Element]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/identify/index.html b/doc/1.7_rc1/dom/element/identify/index.html new file mode 100644 index 000000000..18f00a764 --- /dev/null +++ b/doc/1.7_rc1/dom/element/identify/index.html @@ -0,0 +1,327 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.identify + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.identify +

    + + + + +
    +
    +
    +
    +
    +
    Element.identify(element) → String
    + + +

    Returns element's ID. If element does not have an ID, one is +generated, assigned to element, and returned.

    + +
    Examples
    + +

    Original HTML:

    + +
      <ul>
    +    <li id="apple">apple</li>
    +    <li>orange</li>
    +  </ul>
    +
    +
    + +

    JavaScript:

    + +
      $('apple').identify();
    +  // -> 'apple'
    +   $('apple').next().identify();
    +  // -> 'anonymous_element_1'
    +
    +
    + +

    Resulting HTML:

    + +
      <ul>
    +    <li id="apple">apple</li>
    +    <li id="anonymous_element_1">orange</li>
    +  </ul>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/immediatedescendants/index.html b/doc/1.7_rc1/dom/element/immediatedescendants/index.html new file mode 100644 index 000000000..5beb2d2da --- /dev/null +++ b/doc/1.7_rc1/dom/element/immediatedescendants/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.immediateDescendants + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Element.immediateDescendants +

    + + + + +
    +
    +
    +
    +
    +
    Element.immediateDescendants(element) → [Element…]
    + + +

    This method is deprecated, please see Element.childElements.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/index.html b/doc/1.7_rc1/dom/element/index.html new file mode 100644 index 000000000..9ef90867d --- /dev/null +++ b/doc/1.7_rc1/dom/element/index.html @@ -0,0 +1,695 @@ + + + + + Prototype v1.7_rc1 API documentation | Element + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Element +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    The Element object provides a variety of powerful DOM methods for +interacting with DOM elements — creating them, updating them, +traversing them, etc. You can access these either as methods of Element +itself, passing in the element to work with as the first argument, or as +methods on extended element instances:

    + +
    // Using Element:
    +Element.addClassName('target', 'highlighted');
    + // Using an extended element instance:
    +$('target').addClassName('highlighted');
    +
    +
    + +

    Element is also a constructor for building element instances from scratch, +see new Element for details.

    + +

    Most Element methods return the element instance, so that you can chain +them easily:

    + +
    $('message').addClassName('read').update('I read this message!');
    +
    +
    + +
    More Information
    + +

    For more information about extended elements, check out "How Prototype +extends the DOM", which will walk +you through the inner workings of Prototype's DOM extension mechanism.

    +
    +
    + + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Element.Layout

      + +

      A set of key/value pairs representing measurements of various +dimensions of an element.

      +
    • +
    • +

      Element.Offset

      + +

      A representation of the top- and left-offsets of an element relative to +another.

      +
    • +
    +
    +
    + + + + +
    +
    +

    Includes

    +
    + +
    + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Element

    +
    +
    + + + + + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/insert/index.html b/doc/1.7_rc1/dom/element/insert/index.html new file mode 100644 index 000000000..73a4eef62 --- /dev/null +++ b/doc/1.7_rc1/dom/element/insert/index.html @@ -0,0 +1,352 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.insert + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.insert +

    + + + + +
    +
    +
    +
    +
    +
    Element.insert(element, content) → Element
    + + + +

    Inserts content above, below, at the top, and/or at the bottom of +the given element, depending on the option(s) given.

    + +

    insert accepts content in any of these forms:

    + +
      +
    • String: A string of HTML to be parsed and rendered
    • +
    • Element: An Element instance to insert
    • +
    • ...any object with a toElement method: The method is called and the resulting element used
    • +
    • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
    • +
    + +

    The content argument can be the content to insert, in which case the +implied insertion point is bottom, or an object that specifies one or +more insertion points (e.g., { bottom: "foo", top: "bar" }).

    + +

    Accepted insertion points are:

    + +
      +
    • before (as element's previous sibling)
    • +
    • after (as element's next sibling)
    • +
    • top (as element's first child)
    • +
    • bottom (as element's last child)
    • +
    + +

    Note that if the inserted HTML contains any <script> tag, these will be +automatically evaluated after the insertion (insert internally calls +String.evalScripts when inserting HTML).

    + +
    Examples
    + +

    Insert the given HTML at the bottom of the element (using the default):

    + +
    $('myelement').insert("<p>HTML to append</p>");
    + $('myelement').insert({
    +  top: new Element('img', {src: 'logo.png'})
    +});
    +
    +
    + +

    Put hrs before and after the element:

    + +
    $('myelement').insert({
    +  before: "<hr>",
    +  after: "<hr>"
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/inspect/index.html b/doc/1.7_rc1/dom/element/inspect/index.html new file mode 100644 index 000000000..f6bc45178 --- /dev/null +++ b/doc/1.7_rc1/dom/element/inspect/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.inspect +

    + + + + +
    +
    +
    +
    +
    +
    Element.inspect(element) → String
    + + +

    Returns the debug-oriented string representation of element.

    + +

    For more information on inspect methods, see Object.inspect.

    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu" class="yummy apple">Mutsu</li>
    +  <li id="mcintosh" class="yummy">McIntosh</li>
    +  <li></li>
    +</ul>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('golden-delicious').inspect();
    +// -> '<li id="golden-delicious">'
    + $('mutsu').inspect();
    +// -> '<li id="mutsu" class="yummy apple">'
    + $('mutsu').next().inspect();
    +// -> '<li>'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/layout/composite_properties/index.html b/doc/1.7_rc1/dom/element/layout/composite_properties/index.html new file mode 100644 index 000000000..d64305b1f --- /dev/null +++ b/doc/1.7_rc1/dom/element/layout/composite_properties/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout.COMPOSITE_PROPERTIES + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constant Element.Layout.COMPOSITE_PROPERTIES +

    + + + + +
    +
    +
    +
    +
    +
    + + +

    A list of all composite properties. Composite properties don't map +directly to CSS properties — they're combinations of other +properties.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/layout/index.html b/doc/1.7_rc1/dom/element/layout/index.html new file mode 100644 index 000000000..e9043cc38 --- /dev/null +++ b/doc/1.7_rc1/dom/element/layout/index.html @@ -0,0 +1,446 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Element.Layout +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A set of key/value pairs representing measurements of various +dimensions of an element.

    + +

    Overview

    + +

    The Element.Layout class is a specialized way to measure elements. +It helps mitigate:

    + +
      +
    • The convoluted steps often needed to get common measurements for +elements.
    • +
    • The tendency of browsers to report measurements in non-pixel units.
    • +
    • The quirks that lead some browsers to report inaccurate measurements.
    • +
    • The difficulty of measuring elements that are hidden.
    • +
    + +

    Usage

    + +

    Instantiate an Element.Layout class by passing an element into the +constructor:

    + +
    var layout = new Element.Layout(someElement);
    +
    +
    + +

    You can also use Element.getLayout, if you prefer.

    + +

    Once you have a layout object, retrieve properties using Hash's +familiar get and set syntax.

    + +
    layout.get('width');  //-> 400
    +layout.get('top');    //-> 180
    +
    +
    + +

    The following are the CSS-related properties that can be retrieved. +Nearly all of them map directly to their property names in CSS. (The +only exception is for borders — e.g., border-width instead of +border-left-width.)

    + +
      +
    • height
    • +
    • width
    • +
    • top
    • +
    • left
    • +
    • right
    • +
    • bottom
    • +
    • border-left
    • +
    • border-right
    • +
    • border-top
    • +
    • border-bottom
    • +
    • padding-left
    • +
    • padding-right
    • +
    • padding-top
    • +
    • padding-bottom
    • +
    • margin-top
    • +
    • margin-bottom
    • +
    • margin-left
    • +
    • margin-right
    • +
    + +

    In addition, these "composite" properties can be retrieved:

    + +
      +
    • padding-box-width (width of the content area, from the beginning of +the left padding to the end of the right padding)
    • +
    • padding-box-height (height of the content area, from the beginning +of the top padding to the end of the bottom padding)
    • +
    • border-box-width (width of the content area, from the outer edge of +the left border to the outer edge of the right border)
    • +
    • border-box-height (height of the content area, from the outer edge +of the top border to the outer edge of the bottom border)
    • +
    • margin-box-width (width of the content area, from the beginning of +the left margin to the end of the right margin)
    • +
    • margin-box-height (height of the content area, from the beginning +of the top margin to the end of the bottom margin)
    • +
    + +

    Caching

    + +

    Because these properties can be costly to retrieve, Element.Layout +behaves differently from an ordinary Hash.

    + +

    First: by default, values are "lazy-loaded" — they aren't computed +until they're retrieved. To measure all properties at once, pass +a second argument into the constructor:

    + +
    var layout = new Element.Layout(someElement, true);
    +
    +
    + +

    Second: once a particular value is computed, it's cached. Asking for +the same property again will return the original value without +re-computation. This means that **an instance of Element.Layout +becomes stale when the element's dimensions change**. When this +happens, obtain a new instance.

    + +

    Hidden elements

    + +

    Because it's a common case to want the dimensions of a hidden element +(e.g., for animations), it's possible to measure elements that are +hidden with display: none.

    + +

    However, **it's only possible to measure a hidden element if its parent +is visible**. If its parent (or any other ancestor) is hidden, any +width and height measurements will return 0, as will measurements for +top|bottom|left|right.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Constants

    +
    + +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/layout/new/index.html b/doc/1.7_rc1/dom/element/layout/new/index.html new file mode 100644 index 000000000..6bd2a3cf5 --- /dev/null +++ b/doc/1.7_rc1/dom/element/layout/new/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.7_rc1 API documentation | new Element.Layout + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Element.Layout +

    + + + + +
    +
    +
    +
    +
    +
    new(element[, preCompute])
    +
      +
    • + element + (Element) + – The element to be measured. +
    • +
    • + preCompute + (Boolean) + – Whether to compute all values at once. +
    • +
    + + +

    Declare a new layout hash.

    + +

    The preCompute argument determines whether measurements will be +lazy-loaded or not. If you plan to use many different measurements, +it's often more performant to pre-compute, as it minimizes the +amount of overhead needed to measure. If you need only one or two +measurements, it's probably not worth it.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/layout/properties/index.html b/doc/1.7_rc1/dom/element/layout/properties/index.html new file mode 100644 index 000000000..d6e7d6956 --- /dev/null +++ b/doc/1.7_rc1/dom/element/layout/properties/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout.PROPERTIES + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constant Element.Layout.PROPERTIES +

    + + + + +
    +
    +
    +
    +
    +
    + + +

    A list of all measurable properties.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/layout/prototype/get/index.html b/doc/1.7_rc1/dom/element/layout/prototype/get/index.html new file mode 100644 index 000000000..99164bb58 --- /dev/null +++ b/doc/1.7_rc1/dom/element/layout/prototype/get/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout#get + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Layout#get +

    + + + + +
    +
    +
    +
    +
    +
    Element.Layout#get(property) → Number
    + + + +

    Retrieve the measurement specified by property. Will throw an error +if the property is invalid.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/layout/prototype/tocss/index.html b/doc/1.7_rc1/dom/element/layout/prototype/tocss/index.html new file mode 100644 index 000000000..51b61c83a --- /dev/null +++ b/doc/1.7_rc1/dom/element/layout/prototype/tocss/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout#toCSS + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Layout#toCSS +

    + + + + +
    +
    +
    +
    +
    +
    Element.Layout#toCSS([keys...]) → Object
    +
      +
    • + keys + (String) + – A space-separated list of keys to include. +
    • +
    + + +

    Converts the layout hash to a plain object of CSS property/value +pairs, optionally including only the given keys.

    + +

    Keys can be passed into this method as individual arguments _or_ +separated by spaces within a string.

    + +
    // Equivalent statements:
    +someLayout.toCSS('top', 'bottom', 'left', 'right');
    +someLayout.toCSS('top bottom left right');
    +
    +
    + +

    Useful for passing layout properties to Element.setStyle.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/makeclipping/index.html b/doc/1.7_rc1/dom/element/makeclipping/index.html new file mode 100644 index 000000000..e4ade59e1 --- /dev/null +++ b/doc/1.7_rc1/dom/element/makeclipping/index.html @@ -0,0 +1,344 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.makeClipping + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.makeClipping +

    + + + + +
    +
    +
    +
    +
    +
    Element.makeClipping(element) → Element
    + + +

    Simulates the poorly-supported CSS clip property by setting element's +overflow value to hidden.

    + +

    To undo clipping, use Element.undoClipping.

    + +

    The visible area is determined by element's width and height.

    + +
    Example
    + +
    <div id="framer">
    +  <img src="/assets/2007/1/14/chairs.jpg" alt="example" />
    +</div>
    +
    +
    + +

    Then:

    + +
    $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +// -> Element
    +
    +
    + +

    Another example:

    + +
    <a id="clipper" href="#">Click me to try it out.</a>
    + <div id="framer">
    +  <img src="/assets/2007/2/24/chairs.jpg" alt="example" />
    +</div>
    + <script type="text/javascript" charset="utf-8">
    +  var Example = {
    +    clip: function(){
    +      $('clipper').update('undo clipping!');
    +      $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +    },
    +    unClip: function(){
    +      $('clipper').update('clip!');
    +      $('framer').undoClipping();
    +    },
    +    toggleClip: function(event){
    +      if($('clipper').innerHTML == 'undo clipping!') Example.unClip();
    +      else Example.clip();
    +      Event.stop(event);
    +    }
    +  };
    +  Event.observe('clipper', 'click', Example.toggleClip);
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/makepositioned/index.html b/doc/1.7_rc1/dom/element/makepositioned/index.html new file mode 100644 index 000000000..d912d15ff --- /dev/null +++ b/doc/1.7_rc1/dom/element/makepositioned/index.html @@ -0,0 +1,302 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.makePositioned + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.makePositioned +

    + + + + +
    +
    +
    +
    +
    +
    Element.makePositioned(element) → Element
    + + +

    Allows for the easy creation of a CSS containing block by setting +element's CSS position to relative if its initial position is +either static or undefined.

    + +

    To revert back to element's original CSS position, use +Element.undoPositioned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/match/index.html b/doc/1.7_rc1/dom/element/match/index.html new file mode 100644 index 000000000..9ee14407b --- /dev/null +++ b/doc/1.7_rc1/dom/element/match/index.html @@ -0,0 +1,330 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.match +

    + + + + +
    +
    +
    +
    +
    +
    Element.match(element, selector) → boolean
    +
      +
    • + selector + (String) + – A CSS selector. +
    • +
    + + +

    Checks if element matches the given CSS selector.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <ul>
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +  </li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('fruits').match('ul');
    +// -> true
    + $('mcintosh').match('li#mcintosh.yummy');
    +// -> true
    + $('fruits').match('p');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/measure/index.html b/doc/1.7_rc1/dom/element/measure/index.html new file mode 100644 index 000000000..a48a5c79b --- /dev/null +++ b/doc/1.7_rc1/dom/element/measure/index.html @@ -0,0 +1,303 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.measure + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.measure +

    + + + + +
    +
    +
    +
    +
    +
    Element.measure(element, property) → Number
    + + +

    Gives the pixel value of element's dimension specified by +property.

    + +

    Useful for one-off measurements of elements. If you find yourself +calling this method frequently over short spans of code, you might want +to call Element.getLayout and operate on the Element.Layout +object itself (thereby taking advantage of measurement caching).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/methods/index.html b/doc/1.7_rc1/dom/element/methods/index.html new file mode 100644 index 000000000..858bf3386 --- /dev/null +++ b/doc/1.7_rc1/dom/element/methods/index.html @@ -0,0 +1,313 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Methods + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + mixin Element.Methods +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Element.Methods is a mixin for DOM elements. The methods of this object +are accessed through the $ utility or through the Element object and +shouldn't be accessed directly.

    + +
    Examples
    + +

    Hide the element

    + +
    $(element).hide();
    +
    +
    + +

    Return an Enumerable of all descendant nodes of the element with the id +"article"

    + +
    $('articles').descendants();
    +
    +
    +
    +
    + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/new/index.html b/doc/1.7_rc1/dom/element/new/index.html new file mode 100644 index 000000000..4e120446a --- /dev/null +++ b/doc/1.7_rc1/dom/element/new/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | new Element + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Element +

    + + + + +
    +
    +
    +
    +
    +
    new(tagName[, attributes])
    +
      +
    • + tagName + (String) + – The name of the HTML element to create. +
    • +
    • + attributes + (Object) + – An optional group of attribute/value pairs to set on the element. +
    • +
    + + +

    Creates an HTML element with tagName as the tag name, optionally with the +given attributes. This can be markedly more concise than working directly +with the DOM methods, and takes advantage of Prototype's workarounds for +various browser issues with certain attributes:

    + +
    Example
    + +
    // The old way:
    +var a = document.createElement('a');
    +a.setAttribute('class', 'foo');
    +a.setAttribute('href', '/foo.html');
    +a.appendChild(document.createTextNode("Next page"));
    + // The new way:
    +var a = new Element('a', {'class': 'foo', href: '/foo.html'}).update("Next page");
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/next/index.html b/doc/1.7_rc1/dom/element/next/index.html new file mode 100644 index 000000000..94b101e6a --- /dev/null +++ b/doc/1.7_rc1/dom/element/next/index.html @@ -0,0 +1,411 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.next + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.next +

    + + + + +
    +
    +
    +
    +
    +
    Element.next(element[, expression[, index = 0]]) → Element
    Element.next(element[, index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first following sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all following siblings are considered. If none matches these +criteria, undefined is returned.

    + +
    More information
    + +

    The Element.next method is part of Prototype's ultimate DOM traversal +toolkit (check out Element.up, Element.down and +Element.previous for some more Prototypish niceness). It allows +precise index-based and/or CSS expression-based selection of any of +element's following siblings. (Note that two elements are considered +siblings if they have the same parent, so for example, the head and +body elements are siblings—their parent is the html element.)

    + +

    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 (see +Element.extend) allowing chaining:

    + +
    $(element).down(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's following sibling is returned +(this is similar as calling nextSibling except Element.next returns an +already extended element).

    + +

    If index is defined, element's corresponding following sibling is +returned. (This is equivalent to selecting an element from the array of +elements returned by the method Element.nextSiblings). Note that the +sibling right below element has an index of 0.

    + +

    If expression is defined, Element.next will return the element first +following sibling that matches it.

    + +

    If both expression and index are defined, Element.next will collect +all of element's following siblings matching the given CSS expression +and will return the one at the specified index.

    + +

    In all of the above cases, if no following sibling is found, +undefined will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3 id="title">Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red" class="yummy">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first sibling after "#title":

    + +
    $('title').next();
    +// or:
    +$('title').next(0);
    +// -> ul#list-of-apples
    +
    +
    + +

    Get the second sibling after "#title":

    + +
    $('title').next(1);
    +// -> p#saying
    +
    +
    + +

    Get the first sibling after "#title" with node name "p":

    + +
    $('title').next('p');
    +// -> p#sayings
    +
    +
    + +

    Get the first sibling after "#golden-delicious" with class name "yummy":

    + +
    $('golden-delicious').next('.yummy');
    +// -> li#mcintosh
    +
    +
    + +

    Get the second sibling after "#golden-delicious" with class name "yummy":

    + +
    $('golden-delicious').next('.yummy', 1);
    +// -> li#ida-red
    +
    +
    + +

    Try to get the first sibling after "#ida-red":

    + +
    $('ida-red').next();
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/nextsiblings/index.html b/doc/1.7_rc1/dom/element/nextsiblings/index.html new file mode 100644 index 000000000..3de5a93cd --- /dev/null +++ b/doc/1.7_rc1/dom/element/nextsiblings/index.html @@ -0,0 +1,329 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.nextSiblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.nextSiblings +

    + + + + +
    +
    +
    +
    +
    +
    Element.nextSiblings(element) → [Element…]
    + + +

    Collects all of element's next siblings and returns them as an Array +of elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the head and body elements are siblings (their parent is the html +element). Next-siblings are simply the ones which follow element in the +document.

    + +

    The returned Array reflects the siblings order in the document +(e.g. an index of 0 refers to the sibling right below element).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mutsu').nextSiblings();
    +// -> [li#mcintosh, li#ida-red]
    + $('ida-red').nextSiblings();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/observe/index.html b/doc/1.7_rc1/dom/element/observe/index.html new file mode 100644 index 000000000..40967c0c2 --- /dev/null +++ b/doc/1.7_rc1/dom/element/observe/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.observe + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.observe +

    + + + + +
    +
    +
    +
    +
    +
    Element.observe(element, eventName, handler) → Element
    + + +

    See Event.observe.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/offset/index.html b/doc/1.7_rc1/dom/element/offset/index.html new file mode 100644 index 000000000..8c5aeb681 --- /dev/null +++ b/doc/1.7_rc1/dom/element/offset/index.html @@ -0,0 +1,332 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Element.Offset +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A representation of the top- and left-offsets of an element relative to +another.

    + +

    All methods that compute offsets return an instance of Element.Offset.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/offset/new/index.html b/doc/1.7_rc1/dom/element/offset/new/index.html new file mode 100644 index 000000000..e936123f5 --- /dev/null +++ b/doc/1.7_rc1/dom/element/offset/new/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | new Element.Offset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Element.Offset +

    + + + + +
    +
    +
    +
    +
    +
    new(left, top)
    + + +

    Instantiates an Element.Offset. You shouldn't need to call this +directly.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/offset/prototype/inspect/index.html b/doc/1.7_rc1/dom/element/offset/prototype/inspect/index.html new file mode 100644 index 000000000..462ae7d76 --- /dev/null +++ b/doc/1.7_rc1/dom/element/offset/prototype/inspect/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Offset#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Element.Offset#inspect() → String
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/offset/prototype/relativeto/index.html b/doc/1.7_rc1/dom/element/offset/prototype/relativeto/index.html new file mode 100644 index 000000000..0b4b1b537 --- /dev/null +++ b/doc/1.7_rc1/dom/element/offset/prototype/relativeto/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset#relativeTo + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Offset#relativeTo +

    + + + + +
    +
    +
    +
    +
    +
    Element.Offset#relativeTo(offset) → Element.Offset
    +
      +
    • + offset + (Element.Offset) + – Another offset to compare to. +
    • +
    + + +

    Returns a new Element.Offset with its origin at the given +offset. Useful for determining an element's distance from another +arbitrary element.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/offset/prototype/toarray/index.html b/doc/1.7_rc1/dom/element/offset/prototype/toarray/index.html new file mode 100644 index 000000000..55078ba87 --- /dev/null +++ b/doc/1.7_rc1/dom/element/offset/prototype/toarray/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Offset#toArray +

    + + + + +
    +
    +
    +
    +
    +
    Element.Offset#toArray() → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/offset/prototype/tostring/index.html b/doc/1.7_rc1/dom/element/offset/prototype/tostring/index.html new file mode 100644 index 000000000..d96ebfd69 --- /dev/null +++ b/doc/1.7_rc1/dom/element/offset/prototype/tostring/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset#toString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Offset#toString +

    + + + + +
    +
    +
    +
    +
    +
    Element.Offset#toString() → String
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/on/index.html b/doc/1.7_rc1/dom/element/on/index.html new file mode 100644 index 000000000..99d2ea8b0 --- /dev/null +++ b/doc/1.7_rc1/dom/element/on/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.on + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.on +

    + + + + +
    +
    +
    +
    +
    +
    Element.on(element, eventName[, selector], callback) → Element
    + + +

    See Event.on.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/positionedoffset/index.html b/doc/1.7_rc1/dom/element/positionedoffset/index.html new file mode 100644 index 000000000..ee2357e60 --- /dev/null +++ b/doc/1.7_rc1/dom/element/positionedoffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.positionedOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.positionedOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element.positionedOffset(element) → Element.Offset
    + + +

    Returns element's offset relative to its closest positioned ancestor +(the element that would be returned by Element.getOffsetParent).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/previous/index.html b/doc/1.7_rc1/dom/element/previous/index.html new file mode 100644 index 000000000..5dbff5736 --- /dev/null +++ b/doc/1.7_rc1/dom/element/previous/index.html @@ -0,0 +1,411 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.previous + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.previous +

    + + + + +
    +
    +
    +
    +
    +
    Element.previous(element[, expression[, index = 0]]) → Element
    Element.previous(element[, index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first previous sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all previous siblings are considered. If none matches these +criteria, undefined is returned.

    + +
    More information
    + +

    The Element.previous method is part of Prototype's ultimate DOM +traversal toolkit (check out Element.up, Element.down and +Element.next for some more Prototypish niceness). It allows precise +index-based and/or CSS expression-based selection of any of element's +previous siblings. (Note that two elements are considered siblings if +they have the same parent, so for example, the head and body elements +are siblings—their parent is the html element.)

    + +

    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 (see +Element.extend) allowing chaining:

    + +
    $(element).down('p').previous('ul', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's previous sibling is returned +(this is similar as calling previousSibling except Element.previous +returns an already extended element).

    + +

    If index is defined, element's corresponding previous sibling is +returned. (This is equivalent to selecting an element from the array of +elements returned by the method Element.previousSiblings). Note that +the sibling right above element has an index of 0.

    + +

    If expression is defined, Element.previous will return the element +first previous sibling that matches it.

    + +

    If both expression and index are defined, Element.previous will +collect all of element's previous siblings matching the given CSS +expression and will return the one at the specified index.

    + +

    In all of the above cases, if no previous sibling is found, +undefined will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3>Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious" class="yummy">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first previous sibling of "#saying":

    + +
    $('saying').previous();
    +// or:
    +$('saying').previous(0);
    +// -> ul#list-of-apples
    +
    +
    + +

    Get the second previous sibling of "#saying":

    + +
    $('saying').previous(1);
    +// -> h3
    +
    +
    + +

    Get the first previous sibling of "#saying" with node name "h3":

    + +
    $('saying').previous('h3');
    +// -> h3
    +
    +
    + +

    Get the first previous sibling of "#ida-red" with class name "yummy":

    + +
    $('ida-red').previous('.yummy');
    +// -> li#mutsu
    +
    +
    + +

    Get the second previous sibling of "#ida-red" with class name "yummy":

    + +
    $('ida-red').previous('.yummy', 1);
    +// -> li#golden-delicious
    +
    +
    + +

    Try to get the sixth previous sibling of "#ida-red":

    + +
    $('ida-red').previous(5);
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/previoussiblings/index.html b/doc/1.7_rc1/dom/element/previoussiblings/index.html new file mode 100644 index 000000000..4b13f1ef7 --- /dev/null +++ b/doc/1.7_rc1/dom/element/previoussiblings/index.html @@ -0,0 +1,330 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.previousSiblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.previousSiblings +

    + + + + +
    +
    +
    +
    +
    +
    Element.previousSiblings(element) → [Element…]
    + + +

    Collects all of element's previous siblings and returns them as an +Array of elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the <head> and <body> elements are siblings (their parent is the +<html> element). Previous-siblings are simply the ones which precede +element in the document.

    + +

    The returned Array reflects the siblings inversed order in the +document (e.g. an index of 0 refers to the lowest sibling i.e., the one +closest to element).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mcintosh').previousSiblings();
    +// -> [li#mutsu, li#golden-delicious]
    + $('golden-delicious').previousSiblings();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/absolutize/index.html b/doc/1.7_rc1/dom/element/prototype/absolutize/index.html new file mode 100644 index 000000000..7f06e39aa --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/absolutize/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#absolutize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#absolutize +

    + + + + +
    +
    +
    +
    +
    +
    Element#absolutize() → Element
    + + +

    Turns element into an absolutely-positioned element without +changing its position in the page layout.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/addclassname/index.html b/doc/1.7_rc1/dom/element/prototype/addclassname/index.html new file mode 100644 index 000000000..f3a5d69da --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/addclassname/index.html @@ -0,0 +1,322 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#addClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#addClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element#addClassName(className) → Element
    +
      +
    • + className + (String) + – The class name to add. +
    • +
    + + +

    Adds the given CSS class to element.

    + +
    Example
    + +

    Assuming this HTML:

    + +
    <div id="mutsu" class="apple fruit"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').className;
    +// -> 'apple fruit'
    +$('mutsu').addClassName('food');
    +$('mutsu').className;
    +// -> 'apple fruit food'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/adjacent/index.html b/doc/1.7_rc1/dom/element/prototype/adjacent/index.html new file mode 100644 index 000000000..b896f4e05 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/adjacent/index.html @@ -0,0 +1,331 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#adjacent + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#adjacent +

    + + + + +
    +
    +
    +
    +
    +
    Element#adjacent(selector...) → [Element…]
    +
      +
    • + selector + (String) + – A CSS selector. +
    • +
    + + +

    Finds all siblings of the current element that match the given +selector(s). If you provide multiple selectors, siblings matching any +of the selectors are included. If a sibling matches multiple selectors, +it is only included once. The order of the returned array is not defined.

    + +
    Example
    + +

    Assuming this list:

    + +
    <ul id="cities">
    +  <li class="us" id="nyc">New York</li>
    +  <li class="uk" id="lon">London</li>
    +  <li class="us" id="chi">Chicago</li>
    +  <li class="jp" id="tok">Tokyo</li>
    +  <li class="us" id="la">Los Angeles</li>
    +  <li class="us" id="aus">Austin</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('nyc').adjacent('li.us');
    +// -> [li#chi, li#la, li#aus]
    +$('nyc').adjacent('li.uk', 'li.jp');
    +// -> [li#lon, li#tok]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/ancestors/index.html b/doc/1.7_rc1/dom/element/prototype/ancestors/index.html new file mode 100644 index 000000000..5a6a0600e --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/ancestors/index.html @@ -0,0 +1,327 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#ancestors + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#ancestors +

    + + + + +
    +
    +
    +
    +
    +
    Element#ancestors() → [Element…]
    + + +

    Collects all of element's ancestor elements and returns them as an +array of extended elements.

    + +

    The returned array's first element is element's direct ancestor (its +parentNode), the second one is its grandparent, and so on until the +<html> element is reached. <html> will always be the last member of +the array. Calling ancestors on the <html> element will return an +empty array.

    + +
    Example
    + +

    Assuming:

    + +
    <html>
    +[...]
    +  <body>
    +    <div id="father">
    +      <div id="kid">
    +      </div>
    +    </div>
    +  </body>
    +</html>
    +
    +
    + +

    Then:

    + +
    $('kid').ancestors();
    +// -> [div#father, body, html]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/childelements/index.html b/doc/1.7_rc1/dom/element/prototype/childelements/index.html new file mode 100644 index 000000000..cba70ad65 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/childelements/index.html @@ -0,0 +1,328 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#childElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#childElements +

    + + + + +
    +
    +
    +
    +
    +
    Element#childElements() → [Element…]
    + + +

    Collects all of the element's children and returns them as an array of +Element.extended elements, in document order. The first +entry in the array is the topmost child of element, the next is the +child after that, etc.

    + +

    Like all of Prototype's DOM traversal methods, Element.childElements +ignores text nodes and returns element nodes only.

    + +
    Example
    + +

    Assuming:

    + +
    <div id="australopithecus">
    +  Some text in a text node
    +  <div id="homo-erectus">
    +    <div id="homo-neanderthalensis"></div>
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('australopithecus').childElements();
    +// -> [div#homo-erectus]
    + $('homo-erectus').childElements();
    +// -> [div#homo-neanderthalensis, div#homo-sapiens]
    + $('homo-sapiens').childElements();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/classnames/index.html b/doc/1.7_rc1/dom/element/prototype/classnames/index.html new file mode 100644 index 000000000..6e7924849 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/classnames/index.html @@ -0,0 +1,303 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#classNames + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Element#classNames +

    + + + + +
    +
    +
    +
    +
    +
    Element#classNames() → [String…]
    + + +

    Returns a new instance of Element.ClassNames, an Enumerable +object used to read and write CSS class names of element.

    + +

    Deprecated, please see Element.addClassName, +Element.removeClassName, and Element.hasClassName. If you want +an array of classnames, you can use $w(element.className).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/cleanwhitespace/index.html b/doc/1.7_rc1/dom/element/prototype/cleanwhitespace/index.html new file mode 100644 index 000000000..df49a8cf1 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/cleanwhitespace/index.html @@ -0,0 +1,339 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#cleanWhitespace + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#cleanWhitespace +

    + + + + +
    +
    +
    +
    +
    +
    Element#cleanWhitespace() → Element
    + + +

    Removes all of element's child text nodes that contain only +whitespace. Returns element.

    + +

    This can be very useful when using standard properties like nextSibling, +previousSibling, firstChild or lastChild to walk the DOM. Usually +you'd only do that if you are interested in all of the DOM nodes, not +just Elements (since if you just need to traverse the Elements in the +DOM tree, you can use Element.up, Element.down, +Element.next, and Element.previous instead).

    + +

    Example

    + +

    Consider the following HTML snippet:

    + +
    <ul id="apples">
    +  <li>Mutsu</li>
    +  <li>McIntosh</li>
    +  <li>Ida Red</li>
    +</ul>
    +
    +
    + +

    Let's grab what we think is the first list item using the raw DOM +method:

    + +
    var element = $('apples');
    +element.firstChild.innerHTML;
    +// -> undefined
    +
    +
    + +

    It's undefined because the firstChild of the apples element is a +text node containing the whitespace after the end of the ul and before +the first li.

    + +

    If we remove the useless whitespace, then firstChild works as expected:

    + +
    var element = $('apples');
    +element.cleanWhitespace();
    +element.firstChild.innerHTML;
    +// -> 'Mutsu'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/clone/index.html b/doc/1.7_rc1/dom/element/prototype/clone/index.html new file mode 100644 index 000000000..3e45dfd17 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/clone/index.html @@ -0,0 +1,307 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#clone +

    + + + + +
    +
    +
    +
    +
    +
    Element#clone(deep) → Element
    +
      +
    • + deep + (Boolean) + – Whether to clone element's descendants as well. +
    • +
    + + +

    Returns a duplicate of element.

    + +

    A wrapper around DOM Level 2 Node#cloneNode, Element.clone cleans up +any expando properties defined by Prototype.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/cloneposition/index.html b/doc/1.7_rc1/dom/element/prototype/cloneposition/index.html new file mode 100644 index 000000000..0e37d62eb --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/cloneposition/index.html @@ -0,0 +1,359 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#clonePosition + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#clonePosition +

    + + + + +
    +
    +
    +
    +
    +
    Element#clonePosition(source[, options]) → Element
    +
      +
    • + source + (Element | String) + – The source element (or its ID). +
    • +
    • + options + (Object) + – The position fields to clone. +
    • +
    + + +

    Clones the position and/or dimensions of source onto the element as +defined by options, with an optional offset for the left and top +properties.

    + +

    Note that the element will be positioned exactly like source whether or +not it is part of the same CSS containing +block.

    + +
    Options
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDefaultDescription
    setLefttrueClones source's left CSS property onto element.
    setToptrueClones source's top CSS property onto element.
    setWidthtrueClones source's width onto element.
    setHeighttrueClones source's width onto element.
    offsetLeft0Number by which to offset element's left CSS property.
    offsetTop0Number by which to offset element's top CSS property.
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/cumulativeoffset/index.html b/doc/1.7_rc1/dom/element/prototype/cumulativeoffset/index.html new file mode 100644 index 000000000..fc1e60102 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/cumulativeoffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#cumulativeOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#cumulativeOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element#cumulativeOffset() → Element.Offset
    + + +

    Returns the offsets of element from the top left corner of the +document.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/cumulativescrolloffset/index.html b/doc/1.7_rc1/dom/element/prototype/cumulativescrolloffset/index.html new file mode 100644 index 000000000..86d17b604 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/cumulativescrolloffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#cumulativeScrollOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#cumulativeScrollOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element#cumulativeScrollOffset() → Element.Offset
    + + +

    Calculates the cumulative scroll offset of an element in nested +scrolling containers.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/descendantof/index.html b/doc/1.7_rc1/dom/element/prototype/descendantof/index.html new file mode 100644 index 000000000..617462b83 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/descendantof/index.html @@ -0,0 +1,325 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#descendantOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#descendantOf +

    + + + + +
    +
    +
    +
    +
    +
    Element#descendantOf(ancestor) → Boolean
    +
      +
    • + ancestor + (Element | String) + – The element to check against (or its ID). +
    • +
    + + +

    Checks if element is a descendant of ancestor.

    + +
    Example
    + +

    Assuming:

    + +
    <div id="australopithecus">
    +  <div id="homo-erectus">
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('homo-sapiens').descendantOf('australopithecus');
    +// -> true
    + $('homo-erectus').descendantOf('homo-sapiens');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/descendants/index.html b/doc/1.7_rc1/dom/element/prototype/descendants/index.html new file mode 100644 index 000000000..f32972ae6 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/descendants/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#descendants + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#descendants +

    + + + + +
    +
    +
    +
    +
    +
    Element#descendants() → [Element…]
    + + +

    Collects all of the element's descendants (its children, their children, +etc.) and returns them as an array of extended elements. As with all of +Prototype's DOM traversal methods, only Elements are returned, other +nodes (text nodes, etc.) are skipped.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/down/index.html b/doc/1.7_rc1/dom/element/prototype/down/index.html new file mode 100644 index 000000000..8696d72da --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/down/index.html @@ -0,0 +1,409 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#down + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#down +

    + + + + +
    +
    +
    +
    +
    +
    Element#down([expression[, index = 0]]) → Element
    Element#down([index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first descendant (or the Nth descendant, if index +is specified) that matches expression. If no expression is +provided, all descendants are considered. If no descendant matches these +criteria, undefined is returned.

    + +
    More information
    + +

    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 +(see Element.extend) allowing chaining:

    + +
    $(element).down(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's first descendant is returned (this +is similar to calling firstChild except Element.down returns an +extended element.

    + +

    If index is defined, element's corresponding descendant is returned. +(This is equivalent to selecting an element from the array of elements +returned by the method Element.descendants.) Note that the first +element has an index of 0.

    + +

    If expression is defined, Element.down will return the first +descendant that matches it. This is a great way to grab the first item in +a list for example (just pass in 'li' as the method's first argument).

    + +

    If both expression and index are defined, Element.down will collect +all the descendants matching the given CSS expression and will return the +one at the specified index.

    + +

    In all of the above cases, if no descendant is found, undefined +will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <ul>
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first descendant of "#fruites":

    + +
    $('fruits').down();
    +// or:
    +$('fruits').down(0);
    +// -> li#apples
    +
    +
    + +

    Get the third descendant of "#fruits":

    + +
    $('fruits').down(3);
    +// -> li#golden-delicious
    +
    +
    + +

    Get the first descendant of "#apples" with the node name "li":

    + +
    $('apples').down('li');
    +// -> li#golden-delicious
    +
    +
    + +

    Get the first descendant of "#apples" with the node name "li" and the +class name "yummy":

    + +
    $('apples').down('li.yummy');
    +// -> li#mutsu
    +
    +
    + +

    Get the second descendant of "#fruits" with the class name "yummy":

    + +
    $('fruits').down('.yummy', 1);
    +// -> li#mcintosh
    +
    +
    + +

    Try to get the ninety-ninth descendant of "#fruits":

    + +
    $('fruits').down(99);
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/empty/index.html b/doc/1.7_rc1/dom/element/prototype/empty/index.html new file mode 100644 index 000000000..e152b9151 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/empty/index.html @@ -0,0 +1,308 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#empty + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#empty +

    + + + + +
    +
    +
    +
    +
    +
    Element#empty() → Element
    + + +

    Tests whether element is empty (i.e., contains only whitespace).

    + +
    Examples
    + +
    <div id="wallet">     </div>
    +<div id="cart">full!</div>
    + $('wallet').empty();
    +// -> true
    + $('cart').empty();
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/fire/index.html b/doc/1.7_rc1/dom/element/prototype/fire/index.html new file mode 100644 index 000000000..fd04859cf --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/fire/index.html @@ -0,0 +1,336 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#fire + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#fire +

    + + + + +
    +
    +
    +
    +
    +
    Element#fire(eventName[, memo[, bubble = true]]) → Event
    + + +

    See Event.fire.

    + +

    Fires a custom event with the current element as its target.

    + +

    Element.fire creates a custom event with the given name, then triggers +it on the given element. The custom event has all the same properties +and methods of native events. Like a native event, it will bubble up +through the DOM unless its propagation is explicitly stopped.

    + +

    The optional second argument will be assigned to the memo property of +the event object so that it can be read by event handlers.

    + +

    Custom events are dispatched synchronously: Element.fire waits until +the event finishes its life cycle, then returns the event itself.

    + +
    Note
    + +

    Element.fire does not support firing native events. All custom event +names must be namespaced (using a colon). This is to avoid custom +event names conflicting with non-standard native DOM events such as +mousewheel and DOMMouseScroll.

    + +
    Examples
    + +
    document.observe("widget:frobbed", function(event) {
    +  console.log("Element with ID (" + event.target.id +
    +   ") frobbed widget #" + event.memo.widgetNumber + ".");
    +});
    + var someNode = $('foo');
    +someNode.fire("widget:frobbed", { widgetNumber: 19 });
    + //-> "Element with ID (foo) frobbed widget #19."
    +
    +
    + +
    Tip
    + +

    Events that have been stopped with Event.stop will have a boolean +stopped property set to true. Since Element.fire returns the custom +event, you can inspect this property to determine whether the event was +stopped.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/firstdescendant/index.html b/doc/1.7_rc1/dom/element/prototype/firstdescendant/index.html new file mode 100644 index 000000000..49b85c761 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/firstdescendant/index.html @@ -0,0 +1,324 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#firstDescendant + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#firstDescendant +

    + + + + +
    +
    +
    +
    +
    +
    Element#firstDescendant() → Element
    + + +

    Returns the first child that is an element.

    + +

    This is opposed to the firstChild DOM property, which will return +any node, including text nodes and comment nodes.

    + +
    Examples
    + +
    <div id="australopithecus">
    +  <div id="homo-erectus"><!-- Latin is super -->
    +    <div id="homo-neanderthalensis"></div>
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('australopithecus').firstDescendant();
    +// -> div#homo-herectus
    + // the DOM property returns any first node
    +$('homo-herectus').firstChild;
    +// -> comment node "Latin is super"
    + // this is what we want!
    +$('homo-herectus').firstDescendant();
    +// -> div#homo-neanderthalensis
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getdimensions/index.html b/doc/1.7_rc1/dom/element/prototype/getdimensions/index.html new file mode 100644 index 000000000..506c64467 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getdimensions/index.html @@ -0,0 +1,326 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getDimensions + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getDimensions +

    + + + + +
    +
    +
    +
    +
    +
    Element#getDimensions() → Object
    + + +

    Finds the computed width and height of element and returns them as +key/value pairs of an object.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    In order to avoid calling the method twice, you should consider caching +the values returned in a variable as shown below. If you only need +element's width or height, consider using Element.getWidth or +Element.getHeight instead.

    + +

    Note that all values are returned as numbers only although they are +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    var dimensions = $('rectangle').getDimensions();
    +// -> {width: 200, height: 100}
    + dimensions.width;
    +// -> 200
    + dimensions.height;
    +// -> 100
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getelementsbyselector/index.html b/doc/1.7_rc1/dom/element/prototype/getelementsbyselector/index.html new file mode 100644 index 000000000..01df2bd7e --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getelementsbyselector/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getElementsBySelector + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getElementsBySelector +

    + + + + +
    +
    +
    +
    +
    +
    Element#getElementsBySelector(selector) → [Element…]
    + + + + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getheight/index.html b/doc/1.7_rc1/dom/element/prototype/getheight/index.html new file mode 100644 index 000000000..b55014197 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getheight/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getHeight + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getHeight +

    + + + + +
    +
    +
    +
    +
    +
    Element#getHeight() → Number
    + + +

    Returns the height of element.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    For performance reasons, if you need to query both width and height of +element, you should consider using Element.getDimensions instead.

    + +

    Note that the value returned is a number only although it is +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    $('rectangle').getHeight();
    +// -> 100
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getlayout/index.html b/doc/1.7_rc1/dom/element/prototype/getlayout/index.html new file mode 100644 index 000000000..a925d7550 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getlayout/index.html @@ -0,0 +1,305 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getLayout + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getLayout +

    + + + + +
    +
    +
    +
    +
    +
    Element#getLayout(preCompute) → Element.Layout
    + + +

    Returns an instance of Element.Layout for measuring an element's +dimensions.

    + +

    Note that this method returns a new Element.Layout object each time +it's called. If you want to take advantage of measurement caching, +retain a reference to one Element.Layout object, rather than calling +Element.getLayout whenever you need a measurement. You should call +Element.getLayout again only when the values in an existing +Element.Layout object have become outdated.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getoffsetparent/index.html b/doc/1.7_rc1/dom/element/prototype/getoffsetparent/index.html new file mode 100644 index 000000000..d0740fd61 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getoffsetparent/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getOffsetParent + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getOffsetParent +

    + + + + +
    +
    +
    +
    +
    +
    Element#getOffsetParent() → Element
    + + +

    Returns element's closest positioned ancestor. If none is found, the +body element is returned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getopacity/index.html b/doc/1.7_rc1/dom/element/prototype/getopacity/index.html new file mode 100644 index 000000000..4b68e8692 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getopacity/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getOpacity + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getOpacity +

    + + + + +
    +
    +
    +
    +
    +
    Element#getOpacity() → String | null
    + + +

    Returns the opacity of the element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getstorage/index.html b/doc/1.7_rc1/dom/element/prototype/getstorage/index.html new file mode 100644 index 000000000..7afdf0d38 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getstorage/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getStorage + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getStorage +

    + + + + +
    +
    +
    +
    +
    +
    Element#getStorage() → Hash
    + + +

    Returns the Hash object that stores custom metadata for this element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getstyle/index.html b/doc/1.7_rc1/dom/element/prototype/getstyle/index.html new file mode 100644 index 000000000..27649f899 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getstyle/index.html @@ -0,0 +1,354 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getStyle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getStyle +

    + + + + +
    +
    +
    +
    +
    +
    Element#getStyle(style) → String | null
    +
      +
    • + style + (String) + – The property name to be retrieved. +
    • +
    + + +

    Returns the given CSS property value of element. The property can be +specified in either its CSS form (font-size) or its camelized form +(fontSize).

    + +

    This method looks up the CSS property of an element whether it was +applied inline or in a stylesheet. It works around browser inconsistencies +regarding float, opacity, which returns a value between 0 +(fully transparent) and 1 (fully opaque), position properties +(left, top, right and bottom) and when getting the dimensions +(width or height) of hidden elements.

    + +
    Examples
    + +
    $(element).getStyle('font-size');
    +// equivalent:
    + $(element).getStyle('fontSize');
    +// -> '12px'
    +
    +
    + +
    Notes
    + +

    Internet Explorer returns literal values while other browsers return +computed values.

    + +

    Consider the following HTML snippet:

    + +
    <style>
    +  #test {
    +    font-size: 12px;
    +    margin-left: 1em;
    +  }
    +</style>
    +<div id="test"></div>
    +
    +
    + +

    Then:

    + +
    $('test').getStyle('margin-left');
    +// -> '1em' in Internet Explorer,
    +// -> '12px' elsewhere.
    +
    +
    + +

    Safari returns null for any non-inline property if the element is +hidden (has display set to 'none').

    + +

    Not all CSS shorthand properties are supported. You may only use the CSS +properties described in the +Document Object Model (DOM) Level 2 Style Specification.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/getwidth/index.html b/doc/1.7_rc1/dom/element/prototype/getwidth/index.html new file mode 100644 index 000000000..379ccddfb --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/getwidth/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getWidth + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getWidth +

    + + + + +
    +
    +
    +
    +
    +
    Element#getWidth() → Number
    + + +

    Returns the width of element.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    For performance reasons, if you need to query both width and height of +element, you should consider using Element.getDimensions instead.

    + +

    Note that the value returned is a number only although it is +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    $('rectangle').getWidth();
    +// -> 200
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/hasattribute/index.html b/doc/1.7_rc1/dom/element/prototype/hasattribute/index.html new file mode 100644 index 000000000..4089bd83d --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/hasattribute/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#hasAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#hasAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element#hasAttribute(attribute) → Boolean
    + + +

    Simulates the standard compliant DOM method +hasAttribute +for browsers missing it (Internet Explorer 6 and 7).

    + +
    Example
    + +
    <a id="link" href="http://prototypejs.org">Prototype</a>
    +
    +
    + +

    Then:

    + +
    $('link').hasAttribute('href');
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/hasclassname/index.html b/doc/1.7_rc1/dom/element/prototype/hasclassname/index.html new file mode 100644 index 000000000..75cb6ee1e --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/hasclassname/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#hasClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#hasClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element#hasClassName(className) → Boolean
    + + +

    Checks for the presence of CSS class className on element.

    + +
    Examples
    + +
    <div id="mutsu" class="apple fruit food"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').hasClassName('fruit');
    +// -> true
    + $('mutsu').hasClassName('vegetable');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/hide/index.html b/doc/1.7_rc1/dom/element/prototype/hide/index.html new file mode 100644 index 000000000..49edaf9db --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/hide/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#hide + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#hide +

    + + + + +
    +
    +
    +
    +
    +
    Element#hide() → Element
    + + +

    Sets display: none on element. Returns element.

    + +
    Examples
    + +

    Hide a single element:

    + +
    <div id="error-message"></div>
    + $('error-message').hide();
    +// -> Element (and hides div#error-message)
    +
    +
    + +

    Hide multiple elements using Enumerable#each:

    + +
    ['content', 'navigation', 'footer'].each(Element.hide);
    +// -> ['content', 'navigation', 'footer']
    +
    +
    + +

    Hide multiple elements using Enumerable#invoke:

    + +
    $('content', 'navigation', 'footer').invoke('hide');
    +// -> [Element, Element, Element]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/identify/index.html b/doc/1.7_rc1/dom/element/prototype/identify/index.html new file mode 100644 index 000000000..50092c889 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/identify/index.html @@ -0,0 +1,327 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#identify + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#identify +

    + + + + +
    +
    +
    +
    +
    +
    Element#identify() → String
    + + +

    Returns element's ID. If element does not have an ID, one is +generated, assigned to element, and returned.

    + +
    Examples
    + +

    Original HTML:

    + +
      <ul>
    +    <li id="apple">apple</li>
    +    <li>orange</li>
    +  </ul>
    +
    +
    + +

    JavaScript:

    + +
      $('apple').identify();
    +  // -> 'apple'
    +   $('apple').next().identify();
    +  // -> 'anonymous_element_1'
    +
    +
    + +

    Resulting HTML:

    + +
      <ul>
    +    <li id="apple">apple</li>
    +    <li id="anonymous_element_1">orange</li>
    +  </ul>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/immediatedescendants/index.html b/doc/1.7_rc1/dom/element/prototype/immediatedescendants/index.html new file mode 100644 index 000000000..58cb82942 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/immediatedescendants/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#immediateDescendants + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Element#immediateDescendants +

    + + + + +
    +
    +
    +
    +
    +
    Element#immediateDescendants() → [Element…]
    + + +

    This method is deprecated, please see Element.childElements.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/insert/index.html b/doc/1.7_rc1/dom/element/prototype/insert/index.html new file mode 100644 index 000000000..7818aeef2 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/insert/index.html @@ -0,0 +1,352 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#insert + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#insert +

    + + + + +
    +
    +
    +
    +
    +
    Element#insert(content) → Element
    + + + +

    Inserts content above, below, at the top, and/or at the bottom of +the given element, depending on the option(s) given.

    + +

    insert accepts content in any of these forms:

    + +
      +
    • String: A string of HTML to be parsed and rendered
    • +
    • Element: An Element instance to insert
    • +
    • ...any object with a toElement method: The method is called and the resulting element used
    • +
    • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
    • +
    + +

    The content argument can be the content to insert, in which case the +implied insertion point is bottom, or an object that specifies one or +more insertion points (e.g., { bottom: "foo", top: "bar" }).

    + +

    Accepted insertion points are:

    + +
      +
    • before (as element's previous sibling)
    • +
    • after (as element's next sibling)
    • +
    • top (as element's first child)
    • +
    • bottom (as element's last child)
    • +
    + +

    Note that if the inserted HTML contains any <script> tag, these will be +automatically evaluated after the insertion (insert internally calls +String.evalScripts when inserting HTML).

    + +
    Examples
    + +

    Insert the given HTML at the bottom of the element (using the default):

    + +
    $('myelement').insert("<p>HTML to append</p>");
    + $('myelement').insert({
    +  top: new Element('img', {src: 'logo.png'})
    +});
    +
    +
    + +

    Put hrs before and after the element:

    + +
    $('myelement').insert({
    +  before: "<hr>",
    +  after: "<hr>"
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/inspect/index.html b/doc/1.7_rc1/dom/element/prototype/inspect/index.html new file mode 100644 index 000000000..9959c64fb --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/inspect/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Element#inspect() → String
    + + +

    Returns the debug-oriented string representation of element.

    + +

    For more information on inspect methods, see Object.inspect.

    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu" class="yummy apple">Mutsu</li>
    +  <li id="mcintosh" class="yummy">McIntosh</li>
    +  <li></li>
    +</ul>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('golden-delicious').inspect();
    +// -> '<li id="golden-delicious">'
    + $('mutsu').inspect();
    +// -> '<li id="mutsu" class="yummy apple">'
    + $('mutsu').next().inspect();
    +// -> '<li>'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/makeclipping/index.html b/doc/1.7_rc1/dom/element/prototype/makeclipping/index.html new file mode 100644 index 000000000..6bd650673 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/makeclipping/index.html @@ -0,0 +1,344 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#makeClipping + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#makeClipping +

    + + + + +
    +
    +
    +
    +
    +
    Element#makeClipping() → Element
    + + +

    Simulates the poorly-supported CSS clip property by setting element's +overflow value to hidden.

    + +

    To undo clipping, use Element.undoClipping.

    + +

    The visible area is determined by element's width and height.

    + +
    Example
    + +
    <div id="framer">
    +  <img src="/assets/2007/1/14/chairs.jpg" alt="example" />
    +</div>
    +
    +
    + +

    Then:

    + +
    $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +// -> Element
    +
    +
    + +

    Another example:

    + +
    <a id="clipper" href="#">Click me to try it out.</a>
    + <div id="framer">
    +  <img src="/assets/2007/2/24/chairs.jpg" alt="example" />
    +</div>
    + <script type="text/javascript" charset="utf-8">
    +  var Example = {
    +    clip: function(){
    +      $('clipper').update('undo clipping!');
    +      $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +    },
    +    unClip: function(){
    +      $('clipper').update('clip!');
    +      $('framer').undoClipping();
    +    },
    +    toggleClip: function(event){
    +      if($('clipper').innerHTML == 'undo clipping!') Example.unClip();
    +      else Example.clip();
    +      Event.stop(event);
    +    }
    +  };
    +  Event.observe('clipper', 'click', Example.toggleClip);
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/makepositioned/index.html b/doc/1.7_rc1/dom/element/prototype/makepositioned/index.html new file mode 100644 index 000000000..3332848a6 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/makepositioned/index.html @@ -0,0 +1,302 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#makePositioned + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#makePositioned +

    + + + + +
    +
    +
    +
    +
    +
    Element#makePositioned() → Element
    + + +

    Allows for the easy creation of a CSS containing block by setting +element's CSS position to relative if its initial position is +either static or undefined.

    + +

    To revert back to element's original CSS position, use +Element.undoPositioned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/match/index.html b/doc/1.7_rc1/dom/element/prototype/match/index.html new file mode 100644 index 000000000..22622e9bb --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/match/index.html @@ -0,0 +1,330 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#match +

    + + + + +
    +
    +
    +
    +
    +
    Element#match(selector) → boolean
    +
      +
    • + selector + (String) + – A CSS selector. +
    • +
    + + +

    Checks if element matches the given CSS selector.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <ul>
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +  </li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('fruits').match('ul');
    +// -> true
    + $('mcintosh').match('li#mcintosh.yummy');
    +// -> true
    + $('fruits').match('p');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/measure/index.html b/doc/1.7_rc1/dom/element/prototype/measure/index.html new file mode 100644 index 000000000..92ae56712 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/measure/index.html @@ -0,0 +1,303 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#measure + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#measure +

    + + + + +
    +
    +
    +
    +
    +
    Element#measure(property) → Number
    + + +

    Gives the pixel value of element's dimension specified by +property.

    + +

    Useful for one-off measurements of elements. If you find yourself +calling this method frequently over short spans of code, you might want +to call Element.getLayout and operate on the Element.Layout +object itself (thereby taking advantage of measurement caching).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/next/index.html b/doc/1.7_rc1/dom/element/prototype/next/index.html new file mode 100644 index 000000000..4be767278 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/next/index.html @@ -0,0 +1,411 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#next + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#next +

    + + + + +
    +
    +
    +
    +
    +
    Element#next([expression[, index = 0]]) → Element
    Element#next([index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first following sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all following siblings are considered. If none matches these +criteria, undefined is returned.

    + +
    More information
    + +

    The Element.next method is part of Prototype's ultimate DOM traversal +toolkit (check out Element.up, Element.down and +Element.previous for some more Prototypish niceness). It allows +precise index-based and/or CSS expression-based selection of any of +element's following siblings. (Note that two elements are considered +siblings if they have the same parent, so for example, the head and +body elements are siblings—their parent is the html element.)

    + +

    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 (see +Element.extend) allowing chaining:

    + +
    $(element).down(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's following sibling is returned +(this is similar as calling nextSibling except Element.next returns an +already extended element).

    + +

    If index is defined, element's corresponding following sibling is +returned. (This is equivalent to selecting an element from the array of +elements returned by the method Element.nextSiblings). Note that the +sibling right below element has an index of 0.

    + +

    If expression is defined, Element.next will return the element first +following sibling that matches it.

    + +

    If both expression and index are defined, Element.next will collect +all of element's following siblings matching the given CSS expression +and will return the one at the specified index.

    + +

    In all of the above cases, if no following sibling is found, +undefined will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3 id="title">Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red" class="yummy">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first sibling after "#title":

    + +
    $('title').next();
    +// or:
    +$('title').next(0);
    +// -> ul#list-of-apples
    +
    +
    + +

    Get the second sibling after "#title":

    + +
    $('title').next(1);
    +// -> p#saying
    +
    +
    + +

    Get the first sibling after "#title" with node name "p":

    + +
    $('title').next('p');
    +// -> p#sayings
    +
    +
    + +

    Get the first sibling after "#golden-delicious" with class name "yummy":

    + +
    $('golden-delicious').next('.yummy');
    +// -> li#mcintosh
    +
    +
    + +

    Get the second sibling after "#golden-delicious" with class name "yummy":

    + +
    $('golden-delicious').next('.yummy', 1);
    +// -> li#ida-red
    +
    +
    + +

    Try to get the first sibling after "#ida-red":

    + +
    $('ida-red').next();
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/nextsiblings/index.html b/doc/1.7_rc1/dom/element/prototype/nextsiblings/index.html new file mode 100644 index 000000000..e4306289f --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/nextsiblings/index.html @@ -0,0 +1,329 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#nextSiblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#nextSiblings +

    + + + + +
    +
    +
    +
    +
    +
    Element#nextSiblings() → [Element…]
    + + +

    Collects all of element's next siblings and returns them as an Array +of elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the head and body elements are siblings (their parent is the html +element). Next-siblings are simply the ones which follow element in the +document.

    + +

    The returned Array reflects the siblings order in the document +(e.g. an index of 0 refers to the sibling right below element).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mutsu').nextSiblings();
    +// -> [li#mcintosh, li#ida-red]
    + $('ida-red').nextSiblings();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/observe/index.html b/doc/1.7_rc1/dom/element/prototype/observe/index.html new file mode 100644 index 000000000..9bafda775 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/observe/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#observe + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#observe +

    + + + + +
    +
    +
    +
    +
    +
    Element#observe(eventName, handler) → Element
    + + +

    See Event.observe.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/on/index.html b/doc/1.7_rc1/dom/element/prototype/on/index.html new file mode 100644 index 000000000..292714444 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/on/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#on + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#on +

    + + + + +
    +
    +
    +
    +
    +
    Element#on(eventName[, selector], callback) → Element
    + + +

    See Event.on.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/positionedoffset/index.html b/doc/1.7_rc1/dom/element/prototype/positionedoffset/index.html new file mode 100644 index 000000000..d88d0b543 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/positionedoffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#positionedOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#positionedOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element#positionedOffset() → Element.Offset
    + + +

    Returns element's offset relative to its closest positioned ancestor +(the element that would be returned by Element.getOffsetParent).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/previous/index.html b/doc/1.7_rc1/dom/element/prototype/previous/index.html new file mode 100644 index 000000000..b7024e3b0 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/previous/index.html @@ -0,0 +1,411 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#previous + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#previous +

    + + + + +
    +
    +
    +
    +
    +
    Element#previous([expression[, index = 0]]) → Element
    Element#previous([index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first previous sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all previous siblings are considered. If none matches these +criteria, undefined is returned.

    + +
    More information
    + +

    The Element.previous method is part of Prototype's ultimate DOM +traversal toolkit (check out Element.up, Element.down and +Element.next for some more Prototypish niceness). It allows precise +index-based and/or CSS expression-based selection of any of element's +previous siblings. (Note that two elements are considered siblings if +they have the same parent, so for example, the head and body elements +are siblings—their parent is the html element.)

    + +

    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 (see +Element.extend) allowing chaining:

    + +
    $(element).down('p').previous('ul', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's previous sibling is returned +(this is similar as calling previousSibling except Element.previous +returns an already extended element).

    + +

    If index is defined, element's corresponding previous sibling is +returned. (This is equivalent to selecting an element from the array of +elements returned by the method Element.previousSiblings). Note that +the sibling right above element has an index of 0.

    + +

    If expression is defined, Element.previous will return the element +first previous sibling that matches it.

    + +

    If both expression and index are defined, Element.previous will +collect all of element's previous siblings matching the given CSS +expression and will return the one at the specified index.

    + +

    In all of the above cases, if no previous sibling is found, +undefined will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3>Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious" class="yummy">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first previous sibling of "#saying":

    + +
    $('saying').previous();
    +// or:
    +$('saying').previous(0);
    +// -> ul#list-of-apples
    +
    +
    + +

    Get the second previous sibling of "#saying":

    + +
    $('saying').previous(1);
    +// -> h3
    +
    +
    + +

    Get the first previous sibling of "#saying" with node name "h3":

    + +
    $('saying').previous('h3');
    +// -> h3
    +
    +
    + +

    Get the first previous sibling of "#ida-red" with class name "yummy":

    + +
    $('ida-red').previous('.yummy');
    +// -> li#mutsu
    +
    +
    + +

    Get the second previous sibling of "#ida-red" with class name "yummy":

    + +
    $('ida-red').previous('.yummy', 1);
    +// -> li#golden-delicious
    +
    +
    + +

    Try to get the sixth previous sibling of "#ida-red":

    + +
    $('ida-red').previous(5);
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/previoussiblings/index.html b/doc/1.7_rc1/dom/element/prototype/previoussiblings/index.html new file mode 100644 index 000000000..c20b30547 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/previoussiblings/index.html @@ -0,0 +1,330 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#previousSiblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#previousSiblings +

    + + + + +
    +
    +
    +
    +
    +
    Element#previousSiblings() → [Element…]
    + + +

    Collects all of element's previous siblings and returns them as an +Array of elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the <head> and <body> elements are siblings (their parent is the +<html> element). Previous-siblings are simply the ones which precede +element in the document.

    + +

    The returned Array reflects the siblings inversed order in the +document (e.g. an index of 0 refers to the lowest sibling i.e., the one +closest to element).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mcintosh').previousSiblings();
    +// -> [li#mutsu, li#golden-delicious]
    + $('golden-delicious').previousSiblings();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/readattribute/index.html b/doc/1.7_rc1/dom/element/prototype/readattribute/index.html new file mode 100644 index 000000000..da1f4aca3 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/readattribute/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#readAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#readAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element#readAttribute(attributeName) → String | null
    + + +

    Returns the value of element's attribute or null if attribute has +not been specified.

    + +

    This method serves two purposes. First it acts as a simple wrapper around +getAttribute which isn't a "real" function in Safari and Internet +Explorer (it doesn't have .apply or .call for instance). Secondly, it +cleans up the horrible mess Internet Explorer makes when handling +attributes.

    + +
    Examples
    + +
    <a id="tag" href="/tags/prototype" rel="tag" title="view related bookmarks." my_widget="some info.">Prototype</a>
    +
    +
    + +

    Then:

    + +
    $('tag').readAttribute('href');
    +// -> '/tags/prototype'
    + $('tag').readAttribute('title');
    +// -> 'view related bookmarks.'
    + $('tag').readAttribute('my_widget');
    +// -> 'some info.'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/recursivelycollect/index.html b/doc/1.7_rc1/dom/element/prototype/recursivelycollect/index.html new file mode 100644 index 000000000..67af95eaf --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/recursivelycollect/index.html @@ -0,0 +1,334 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#recursivelyCollect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#recursivelyCollect +

    + + + + +
    +
    +
    +
    +
    +
    Element#recursivelyCollect(property) → [Element…]
    + + +

    Recursively collects elements whose relationship to element is +specified by property. property has to be a property (a method +won't do!) of element that points to a single DOM node (e.g., +nextSibling or parentNode).

    + +
    More information
    + +

    This method is used internally by Element.ancestors, +Element.descendants, Element.nextSiblings, +Element.previousSiblings and Element.siblings which offer really +convenient way to grab elements, so directly accessing +Element.recursivelyCollect should seldom be needed. However, if you +are after something out of the ordinary, it is the way to go.

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <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>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('fruits').recursivelyCollect('firstChild');
    +// -> [li#apples, ul#list-of-apples, li#golden-delicious, p]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/relativize/index.html b/doc/1.7_rc1/dom/element/prototype/relativize/index.html new file mode 100644 index 000000000..c03ea59ed --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/relativize/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#relativize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#relativize +

    + + + + +
    +
    +
    +
    +
    +
    Element#relativize() → Element
    + + +

    Turns element into a relatively-positioned element without changing +its position in the page layout.

    + +

    Used to undo a call to Element.absolutize.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/remove/index.html b/doc/1.7_rc1/dom/element/prototype/remove/index.html new file mode 100644 index 000000000..7c2149da6 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/remove/index.html @@ -0,0 +1,329 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#remove + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#remove +

    + + + + +
    +
    +
    +
    +
    +
    Element#remove() → Element
    + + +

    Completely removes element from the document and returns it.

    + +

    If you would rather just hide the element and keep it around for further +use, try Element.hide instead.

    + +
    Examples
    + +
    // Before:
    +<ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('mutsu').remove();
    +// -> Element (and removes li#mutsu)
    +
    +
    + +

    The resulting HTML:

    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/removeclassname/index.html b/doc/1.7_rc1/dom/element/prototype/removeclassname/index.html new file mode 100644 index 000000000..3cf4bc1de --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/removeclassname/index.html @@ -0,0 +1,314 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#removeClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#removeClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element#removeClassName(className) → Element
    + + +

    Removes CSS class className from element.

    + +
    Examples
    + +

    Assuming this HTML:

    + +
    <div id="mutsu" class="apple fruit food"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').removeClassName('food');
    +// -> Element
    + $('mutsu').classNames;
    +// -> 'apple fruit'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/replace/index.html b/doc/1.7_rc1/dom/element/prototype/replace/index.html new file mode 100644 index 000000000..6f7a2fa15 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/replace/index.html @@ -0,0 +1,366 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#replace + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#replace +

    + + + + +
    +
    +
    +
    +
    +
    Element#replace([newContent]) → Element
    + + +

    Replaces element itself with newContent and returns element.

    + +

    Keep in mind that this method returns the element that has just been +removed — not the element that took its place.

    + +

    newContent can be either plain text, an HTML snippet or any JavaScript +object which has a toString() method.

    + +

    If newContent contains any <script> tags, these will be evaluated +after element has been replaced (Element.replace internally calls +String#evalScripts).

    + +

    Note that if no argument is provided, Element.replace will simply +clear element of its content. However, using Element.remove to do so +is both faster and more standard compliant.

    + +
    Examples
    + +
    <div id="food">
    +  <div id="fruits">
    +    <p id="first">Kiwi, banana <em>and</em> apple.</p>
    +  </div>
    +</div>
    +
    +
    + +

    Passing an HTML snippet:

    + +
    $('first').replace('<ul id="favorite"><li>kiwi</li><li>banana</li><li>apple</li></ul>');
    +// -> Element (p#first)
    + $('fruits').innerHTML;
    +// -> '<ul id="favorite"><li>kiwi</li><li>banana</li><li>apple</li></ul>'
    +
    +
    + +

    Again, with a <script> tag thrown in:

    + +
    $('favorite').replace('<p id="still-first">Melon, oranges <em>and</em> grapes.</p><script>alert("removed!")</script>');
    +// -> Element (ul#favorite) and prints "removed!" in an alert dialog.
    + $('fruits').innerHTML;
    +// -> '<p id="still-first">Melon, oranges <em>and</em> grapes.</p>'
    +
    +
    + +

    With plain text:

    + +
    $('still-first').replace('Melon, oranges and grapes.');
    +// -> Element (p#still-first)
    + $('fruits').innerHTML;
    +// -> 'Melon, oranges and grapes.'
    +
    +
    + +

    Finally, relying on the toString() method:

    + +
    $('fruits').replace(123);
    +// -> Element
    + $('food').innerHTML;
    +// -> '123'
    +
    +
    + +
    Warning
    + +

    Using Element.replace as an instance method (e.g., +$('foo').replace('<p>Bar</p>')) causes errors in Opera 9 when used on +input elements. The replace property is reserved on input elements +as part of Web Forms 2. +As a workaround, use the generic version instead +(Element.replace('foo', '<p>Bar</p>')).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/retrieve/index.html b/doc/1.7_rc1/dom/element/prototype/retrieve/index.html new file mode 100644 index 000000000..632ee5084 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/retrieve/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#retrieve + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#retrieve +

    + + + + +
    +
    +
    +
    +
    +
    Element#retrieve(key[, defaultValue]) → ?
    + + +

    Retrieves custom metadata set on element with Element.store.

    + +

    If the value is undefined and defaultValue is given, it will be +stored on the element as its new value for that key, then returned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/scrollto/index.html b/doc/1.7_rc1/dom/element/prototype/scrollto/index.html new file mode 100644 index 000000000..ebcb36764 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/scrollto/index.html @@ -0,0 +1,308 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#scrollTo + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#scrollTo +

    + + + + +
    +
    +
    +
    +
    +
    Element#scrollTo() → Element
    + + +

    Scrolls the window so that element appears at the top of the viewport.

    + +

    This has a similar effect than what would be achieved using +HTML anchors +(except the browser's history is not modified).

    + +
    Example
    + +
    $(element).scrollTo();
    +// -> Element
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/select/index.html b/doc/1.7_rc1/dom/element/prototype/select/index.html new file mode 100644 index 000000000..104d92016 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/select/index.html @@ -0,0 +1,356 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#select +

    + + + + +
    +
    +
    +
    +
    +
    Element#select(expression...) → [Element…]
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Takes an arbitrary number of CSS selectors and returns an array of +descendants of element that match any of them.

    + +

    This method is very similar to $$ but can be used within the context +of one element, rather than the whole document. The supported CSS syntax +is identical, so please refer to the $$ docs for details.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3 title="yummy!">Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious" title="yummy!" >Golden Delicious</li>
    +      <li id="mutsu" title="yummy!">Mutsu</li>
    +      <li id="mcintosh">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('apples').select('[title="yummy!"]');
    +// -> [h3, li#golden-delicious, li#mutsu]
    + $('apples').select( 'p#saying', 'li[title="yummy!"]');
    +// -> [li#golden-delicious, li#mutsu,  p#saying]
    + $('apples').select('[title="disgusting!"]');
    +// -> []
    +
    +
    + +
    Tip
    + +

    Element.select can be used as a pleasant alternative to the native +method getElementsByTagName:

    + +
    var nodes  = $A(someUL.getElementsByTagName('li')).map(Element.extend);
    +var nodes2 = someUL.select('li');
    +
    +
    + +

    In the first example, you must explicitly convert the result set to an +Array (so that Prototype's Enumerable methods can be used) and +must manually call Element.extend on each node (so that custom +instance methods can be used on the nodes). Element.select takes care +of both concerns on its own.

    + +

    If you're using 1.6 or above (and the performance optimizations therein), +the speed difference between these two examples is negligible.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/setopacity/index.html b/doc/1.7_rc1/dom/element/prototype/setopacity/index.html new file mode 100644 index 000000000..9f8aeae0d --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/setopacity/index.html @@ -0,0 +1,313 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#setOpacity + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#setOpacity +

    + + + + +
    +
    +
    +
    +
    +
    Element#setOpacity(opacity) → [Element…]
    + + +

    Sets the visual opacity of an element while working around inconsistencies +in various browsers. The opacity argument should be a floating point +number, where the value of 0 is fully transparent and 1 is fully opaque.

    + +

    Element.setStyle method uses Element.setOpacity internally when needed.

    + +
    Examples
    + +
    var element = $('myelement');
    +// set to 50% transparency
    +element.setOpacity(0.5);
    + // these are equivalent, but allow for setting more than
    +// one CSS property at once:
    +element.setStyle({ opacity: 0.5 });
    +element.setStyle("opacity: 0.5");
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/setstyle/index.html b/doc/1.7_rc1/dom/element/prototype/setstyle/index.html new file mode 100644 index 000000000..d2d4d7065 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/setstyle/index.html @@ -0,0 +1,334 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#setStyle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#setStyle +

    + + + + +
    +
    +
    +
    +
    +
    Element#setStyle(styles) → Element
    + + +

    Modifies element's CSS style properties. Styles are passed as a hash of +property-value pairs in which the properties are specified in their +camelized form.

    + +
    Examples
    + +
    $(element).setStyle({
    +  backgroundColor: '#900',
    +  fontSize: '12px'
    +});
    +// -> Element
    +
    +
    + +
    Notes
    + +

    The method transparently deals with browser inconsistencies for float +(however, as float is a reserved keyword, you must either escape it or +use cssFloat instead) and opacity (which accepts values between 0 +-fully transparent- and 1 -fully opaque-). You can safely use either of +the following across all browsers:

    + +
    $(element).setStyle({
    +  cssFloat: 'left',
    +  opacity: 0.5
    +});
    +// -> Element
    + $(element).setStyle({
    +  'float': 'left', // notice how float is surrounded by single quotes
    +  opacity: 0.5
    +});
    +// -> Element
    +
    +
    + +

    Not all CSS shorthand properties are supported. You may only use the CSS +properties described in the +Document Object Model (DOM) Level 2 Style Specification.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/show/index.html b/doc/1.7_rc1/dom/element/prototype/show/index.html new file mode 100644 index 000000000..465dd24fe --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/show/index.html @@ -0,0 +1,339 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#show + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#show +

    + + + + +
    +
    +
    +
    +
    +
    Element#show() → Element
    + + +

    Removes display: none on element. Returns element.

    + +
    Examples
    + +

    Show a single element:

    + +
    <div id="error-message" style="display:none;"></div>
    + $('error-message').show();
    +// -> Element (and displays div#error-message)
    +
    +
    + +

    Show multiple elements using Enumerable#each:

    + +
    ['content', 'navigation', 'footer'].each(Element.show);
    +// -> ['content', 'navigation', 'footer']
    +
    +
    + +

    Show multiple elements using Enumerable#invoke:

    + +
    $('content', 'navigation', 'footer').invoke('show');
    +// -> [Element, Element, Element]
    +
    +
    + +
    Notes
    + +

    Element.show cannot display elements hidden via CSS stylesheets. +Note that this is not a Prototype limitation but a consequence of how the +CSS display property works.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    + $('hidden-by-css').show(); // DOES NOT WORK!
    +// -> Element (div#error-message is still hidden!)
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/siblings/index.html b/doc/1.7_rc1/dom/element/prototype/siblings/index.html new file mode 100644 index 000000000..e8df983de --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/siblings/index.html @@ -0,0 +1,326 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#siblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#siblings +

    + + + + +
    +
    +
    +
    +
    +
    Element#siblings() → [Element…]
    + + +

    Collects all of element's siblings and returns them as an Array of +elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the head and body elements are siblings (their parent is the html +element).

    + +

    The returned Array reflects the siblings' order in the document (e.g. +an index of 0 refers to element's topmost sibling).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mutsu').siblings();
    +// -> [li#golden-delicious, li#mcintosh, li#ida-red]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/stopobserving/index.html b/doc/1.7_rc1/dom/element/prototype/stopobserving/index.html new file mode 100644 index 000000000..062648b0a --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/stopobserving/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#stopObserving + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#stopObserving +

    + + + + +
    +
    +
    +
    +
    +
    Element#stopObserving([eventName[, handler]]) → Element
    + + +

    See Event.stopObserving.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/store/index.html b/doc/1.7_rc1/dom/element/prototype/store/index.html new file mode 100644 index 000000000..213b88638 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/store/index.html @@ -0,0 +1,299 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#store + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#store +

    + + + + +
    +
    +
    +
    +
    +
    Element#store(key, value) → Element
    + + +

    Stores a key/value pair of custom metadata on the element.

    + +

    The metadata can later be retrieved with Element.retrieve.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/toggle/index.html b/doc/1.7_rc1/dom/element/prototype/toggle/index.html new file mode 100644 index 000000000..7a5261fb3 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/toggle/index.html @@ -0,0 +1,340 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#toggle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#toggle +

    + + + + +
    +
    +
    +
    +
    +
    Element#toggle() → Element
    + + +

    Toggles the visibility of element. Returns element.

    + +
    Examples
    + +
    <div id="welcome-message"></div>
    +<div id="error-message" style="display:none;"></div>
    + $('welcome-message').toggle();
    +// -> Element (and hides div#welcome-message)
    + $('error-message').toggle();
    +// -> Element (and displays div#error-message)
    +
    +
    + +

    Toggle multiple elements using Enumerable#each:

    + +
    ['error-message', 'welcome-message'].each(Element.toggle);
    +// -> ['error-message', 'welcome-message']
    +
    +
    + +

    Toggle multiple elements using Enumerable#invoke:

    + +
    $('error-message', 'welcome-message').invoke('toggle');
    +// -> [Element, Element]
    +
    +
    + +
    Notes
    + +

    Element.toggle cannot display elements hidden via CSS stylesheets. +Note that this is not a Prototype limitation but a consequence of how the +CSS display property works.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    + $('hidden-by-css').toggle(); // WONT' WORK!
    +// -> Element (div#hidden-by-css is still hidden!)
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/toggleclassname/index.html b/doc/1.7_rc1/dom/element/prototype/toggleclassname/index.html new file mode 100644 index 000000000..f176da0a6 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/toggleclassname/index.html @@ -0,0 +1,314 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#toggleClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#toggleClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element#toggleClassName(className) → Element
    + + +

    Toggles the presence of CSS class className on element.

    + +
    Examples
    + +
    <div id="mutsu" class="apple"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').hasClassName('fruit');
    +// -> false
    + $('mutsu').toggleClassName('fruit');
    +// -> element
    + $('mutsu').hasClassName('fruit');
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/undoclipping/index.html b/doc/1.7_rc1/dom/element/prototype/undoclipping/index.html new file mode 100644 index 000000000..3feda562c --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/undoclipping/index.html @@ -0,0 +1,341 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#undoClipping + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#undoClipping +

    + + + + +
    +
    +
    +
    +
    +
    Element#undoClipping() → Element
    + + +

    Sets element's CSS overflow property back to the value it had +before Element.makeClipping was applied.

    + +
    Example
    + +
    <div id="framer">
    +  <img src="/assets/2007/1/14/chairs.jpg" alt="example" />
    +</div>
    +
    +
    + +

    Then:

    + +
    $('framer').undoClipping();
    +// -> Element (and sets the CSS overflow property to its original value).
    +
    +
    + +

    Another example:

    + +
    <a id="clipper" href="#">Click me to try it out.</a>
    + <div id="framer">
    +  <img src="/assets/2007/2/24/chairs_1.jpg" alt="example" />
    +</div>
    + <script type="text/javascript" charset="utf-8">
    +  var Example = {
    +    clip: function(){
    +      $('clipper').update('undo clipping!');
    +      $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +    },
    +    unClip: function(){
    +      $('clipper').update('clip!');
    +      $('framer').undoClipping();
    +    },
    +    toggleClip: function(event){
    +      if($('clipper').innerHTML == 'clip!') Example.clip();
    +      else Example.unClip();
    +      Event.stop(event);
    +    }
    +  };
    +  $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +  Event.observe('clipper', 'click', Example.toggleClip);
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/undopositioned/index.html b/doc/1.7_rc1/dom/element/prototype/undopositioned/index.html new file mode 100644 index 000000000..dc3fa0da3 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/undopositioned/index.html @@ -0,0 +1,302 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#undoPositioned + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#undoPositioned +

    + + + + +
    +
    +
    +
    +
    +
    Element#undoPositioned() → Element
    + + +

    Sets element back to the state it was in before +Element.makePositioned was applied to it.

    + +

    element's absolutely positioned children will now have their positions +set relatively to element's nearest ancestor with a CSS position of +'absolute', 'relative' or 'fixed'.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/up/index.html b/doc/1.7_rc1/dom/element/prototype/up/index.html new file mode 100644 index 000000000..e58f892e1 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/up/index.html @@ -0,0 +1,413 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#up + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#up +

    + + + + +
    +
    +
    +
    +
    +
    Element#up([expression[, index = 0]]) → Element
    Element#up([index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first ancestor (or the Nth ancestor, if index +is specified) that matches expression. If no expression is +provided, all ancestors are considered. If no ancestor matches these +criteria, undefined is returned.

    + +
    More information
    + +

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

    + +

    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 +(see Element.extended) allowing chaining:

    + +
    $(element).up(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's first ancestor is returned (this +is similar to calling parentNode except Element.up returns an already +extended element.

    + +

    If index is defined, element's corresponding ancestor is returned. +(This is equivalent to selecting an element from the array of elements +returned by the method Element.ancestors). Note that the first element +has an index of 0.

    + +

    If expression is defined, Element.up will return the first ancestor +that matches it.

    + +

    If both expression and index are defined, Element.up will collect +all the ancestors matching the given CSS expression and will return the +one at the specified index.

    + +

    In all of the above cases, if no descendant is found, undefined +will be returned.

    + +

    Examples

    + +
    <html>
    +  [...]
    +  <body>
    +    <ul id="fruits">
    +      <li id="apples" class="keeps-the-doctor-away">
    +        <ul>
    +          <li id="golden-delicious">Golden Delicious</li>
    +          <li id="mutsu" class="yummy">Mutsu</li>
    +          <li id="mcintosh" class="yummy">McIntosh</li>
    +          <li id="ida-red">Ida Red</li>
    +        </ul>
    +      </li>
    +    </ul>
    +  </body>
    +</html>
    +
    +
    + +

    Get the first ancestor of "#fruites":

    + +
    $('fruits').up();
    +// or:
    +$('fruits').up(0);
    +// -> body
    +
    +
    + +

    Get the third ancestor of "#mutsu":

    + +
    $('mutsu').up(2);
    +// -> ul#fruits
    +
    +
    + +

    Get the first ancestor of "#mutsu" with the node name "li":

    + +
    $('mutsu').up('li');
    +// -> li#apples
    +
    +
    + +

    Get the first ancestor of "#mutsu" with the class name +"keeps-the-doctor-away":

    + +
    $('mutsu').up('.keeps-the-doctor-away');
    +// -> li#apples
    +
    +
    + +

    Get the second ancestor of "#mutsu" with the node name "ul":

    + +
    $('mutsu').up('ul', 1);
    +// -> ul#fruits
    +
    +
    + +

    Try to get the first ancestor of "#mutsu" with the node name "div":

    + +
    $('mutsu').up('div');
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/update/index.html b/doc/1.7_rc1/dom/element/prototype/update/index.html new file mode 100644 index 000000000..b53b5027f --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/update/index.html @@ -0,0 +1,391 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#update + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#update +

    + + + + +
    +
    +
    +
    +
    +
    Element#update([newContent]) → Element
    + + +

    Replaces the content of element with the newContent argument and +returns element.

    + +

    newContent may be in any of these forms:

    + +
      +
    • String: A string of HTML to be parsed and rendered
    • +
    • Element: An Element instance to insert
    • +
    • ...any object with a toElement method: The method is called and the resulting element used
    • +
    • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
    • +
    + +

    If newContent is omitted, the element's content is blanked out (i.e., +replaced with an empty string).

    + +

    If newContent is a string and contains one or more inline <script> +tags, the scripts are scheduled to be evaluated after a very brief pause +(using Function#defer) to allow the browser to finish updating the +DOM. Note that the scripts are evaluated in the scope of +String#evalScripts, not in the global scope, which has important +ramifications for your vars and functions. +See String#evalScripts for details.

    + +

    Note that this method allows seamless content update of table related +elements in Internet Explorer 6 and beyond.

    + +
    Examples
    + +
    <div id="fruits">carrot, eggplant and cucumber</div>
    +
    +
    + +

    Passing a regular string:

    + +
    $('fruits').update('kiwi, banana and apple');
    +// -> Element
    +$('fruits').innerHTML;
    +// -> 'kiwi, banana and apple'
    +
    +
    + +

    Clearing the element's content:

    + +
    $('fruits').update();
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '' (an empty string)
    +
    +
    + +

    And now inserting an HTML snippet:

    + +
    $('fruits').update('<p>Kiwi, banana <em>and</em> apple.</p>');
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '<p>Kiwi, banana <em>and</em> apple.</p>'
    +
    +
    + +

    ... with a <script> tag thrown in:

    + +
    $('fruits').update('<p>Kiwi, banana <em>and</em> apple.</p><script>alert("updated!")</script>');
    +// -> Element (and prints "updated!" in an alert dialog).
    +$('fruits').innerHTML;
    +// -> '<p>Kiwi, banana <em>and</em> apple.</p>'
    +
    +
    + +

    Relying on the toString() method:

    + +
    $('fruits').update(123);
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '123'
    +
    +
    + +

    Finally, you can do some pretty funky stuff by defining your own +toString() method on your custom objects:

    + +
    var Fruit = Class.create({
    +  initialize: function(fruit){
    +    this.fruit = fruit;
    +  },
    +  toString: function(){
    +    return 'I am a fruit and my name is "' + this.fruit + '".';
    +  }
    +});
    +var apple = new Fruit('apple');
    + $('fruits').update(apple);
    +$('fruits').innerHTML;
    +// -> 'I am a fruit and my name is "apple".'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/viewportoffset/index.html b/doc/1.7_rc1/dom/element/prototype/viewportoffset/index.html new file mode 100644 index 000000000..9d85438cf --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/viewportoffset/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#viewportOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#viewportOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element#viewportOffset() → Array
    + + +

    Returns the X/Y coordinates of element relative to the viewport.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/visible/index.html b/doc/1.7_rc1/dom/element/prototype/visible/index.html new file mode 100644 index 000000000..e2ea44ee2 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/visible/index.html @@ -0,0 +1,336 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#visible + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#visible +

    + + + + +
    +
    +
    +
    +
    +
    Element#visible() → Boolean
    + + +

    Tells whether element is visible (i.e., whether its inline display +CSS property is set to none.

    + +
    Examples
    + +
    <div id="visible"></div>
    +<div id="hidden" style="display: none;"></div>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('visible').visible();
    +// -> true
    + $('hidden').visible();
    +// -> false
    +
    +
    + +
    Notes
    + +

    Styles applied via a CSS stylesheet are not taken into consideration. +Note that this is not a Prototype limitation, it is a CSS limitation.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('hidden-by-css').visible();
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/wrap/index.html b/doc/1.7_rc1/dom/element/prototype/wrap/index.html new file mode 100644 index 000000000..aa46a9787 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/wrap/index.html @@ -0,0 +1,370 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#wrap + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#wrap +

    + + + + +
    +
    +
    +
    +
    +
    Element#wrap(wrapper[, attributes]) → Element
    +
      +
    • + wrapper + (Element | String) + – An element to wrap element inside, or else a string representing the tag name of an element to be created. +
    • +
    • + attributes + (Object) + – A set of attributes to apply to the wrapper element. Refer to the Element constructor for usage. +
    • +
    + + +

    Wraps an element inside another, then returns the wrapper.

    + +

    If the given element exists on the page, Element.wrap will wrap it in +place — its position will remain the same.

    + +

    The wrapper argument can be either an existing Element _or_ a +string representing the tag name of an element to be created. The optional +attributes argument can contain a list of attribute/value pairs that +will be set on the wrapper using Element.writeAttribute.

    + +
    Examples
    + +

    Original HTML:

    + +
    <table id="data">
    +  <tr>
    +    <th>Foo</th>
    +    <th>Bar</th>
    +  </tr>
    +  <tr>
    +    <td>1</td>
    +    <td>2</td>
    +  </tr>
    +</table>
    +
    +
    + +

    JavaScript:

    + +
    // approach 1:
    +var div = new Element('div', { 'class': 'table-wrapper' });
    +$('data').wrap(div);
    + // approach 2:
    +$('data').wrap('div', { 'class': 'table-wrapper' });
    + // Both examples are equivalent &mdash; they return the DIV.
    +
    +
    + +

    Resulting HTML:

    + +
    <div class="table-wrapper">
    +  <table id="data">
    +    <tr>
    +      <th>Foo</th>
    +      <th>Bar</th>
    +    </tr>
    +    <tr>
    +      <td>1</td>
    +      <td>2</td>
    +    </tr>
    +  </table>
    +</div>
    +
    +
    + +
    Warning
    + +

    Using Element.wrap as an instance method (e.g., $('foo').wrap('p')) +causes errors in Internet Explorer when used on textarea elements. The +wrap property is reserved on textarea's as a proprietary extension to +HTML. As a workaround, use the generic version instead +(Element.wrap('foo', 'p')).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/prototype/writeattribute/index.html b/doc/1.7_rc1/dom/element/prototype/writeattribute/index.html new file mode 100644 index 000000000..3bfbd5047 --- /dev/null +++ b/doc/1.7_rc1/dom/element/prototype/writeattribute/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#writeAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#writeAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element#writeAttribute(attribute[, value = true]) → Element
    Element#writeAttribute(attributes) → Element
    + + +

    Adds, specifies or removes attributes passed as either a hash or a +name/value pair.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/readattribute/index.html b/doc/1.7_rc1/dom/element/readattribute/index.html new file mode 100644 index 000000000..6ce6edd53 --- /dev/null +++ b/doc/1.7_rc1/dom/element/readattribute/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.readAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.readAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element.readAttribute(element, attributeName) → String | null
    + + +

    Returns the value of element's attribute or null if attribute has +not been specified.

    + +

    This method serves two purposes. First it acts as a simple wrapper around +getAttribute which isn't a "real" function in Safari and Internet +Explorer (it doesn't have .apply or .call for instance). Secondly, it +cleans up the horrible mess Internet Explorer makes when handling +attributes.

    + +
    Examples
    + +
    <a id="tag" href="/tags/prototype" rel="tag" title="view related bookmarks." my_widget="some info.">Prototype</a>
    +
    +
    + +

    Then:

    + +
    $('tag').readAttribute('href');
    +// -> '/tags/prototype'
    + $('tag').readAttribute('title');
    +// -> 'view related bookmarks.'
    + $('tag').readAttribute('my_widget');
    +// -> 'some info.'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/recursivelycollect/index.html b/doc/1.7_rc1/dom/element/recursivelycollect/index.html new file mode 100644 index 000000000..69cfaf746 --- /dev/null +++ b/doc/1.7_rc1/dom/element/recursivelycollect/index.html @@ -0,0 +1,334 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.recursivelyCollect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.recursivelyCollect +

    + + + + +
    +
    +
    +
    +
    +
    Element.recursivelyCollect(element, property) → [Element…]
    + + +

    Recursively collects elements whose relationship to element is +specified by property. property has to be a property (a method +won't do!) of element that points to a single DOM node (e.g., +nextSibling or parentNode).

    + +
    More information
    + +

    This method is used internally by Element.ancestors, +Element.descendants, Element.nextSiblings, +Element.previousSiblings and Element.siblings which offer really +convenient way to grab elements, so directly accessing +Element.recursivelyCollect should seldom be needed. However, if you +are after something out of the ordinary, it is the way to go.

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <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>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('fruits').recursivelyCollect('firstChild');
    +// -> [li#apples, ul#list-of-apples, li#golden-delicious, p]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/relativize/index.html b/doc/1.7_rc1/dom/element/relativize/index.html new file mode 100644 index 000000000..6d112ac46 --- /dev/null +++ b/doc/1.7_rc1/dom/element/relativize/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.relativize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.relativize +

    + + + + +
    +
    +
    +
    +
    +
    Element.relativize(element) → Element
    + + +

    Turns element into a relatively-positioned element without changing +its position in the page layout.

    + +

    Used to undo a call to Element.absolutize.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/remove/index.html b/doc/1.7_rc1/dom/element/remove/index.html new file mode 100644 index 000000000..7fae5f739 --- /dev/null +++ b/doc/1.7_rc1/dom/element/remove/index.html @@ -0,0 +1,329 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.remove + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.remove +

    + + + + +
    +
    +
    +
    +
    +
    Element.remove(element) → Element
    + + +

    Completely removes element from the document and returns it.

    + +

    If you would rather just hide the element and keep it around for further +use, try Element.hide instead.

    + +
    Examples
    + +
    // Before:
    +<ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('mutsu').remove();
    +// -> Element (and removes li#mutsu)
    +
    +
    + +

    The resulting HTML:

    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/removeclassname/index.html b/doc/1.7_rc1/dom/element/removeclassname/index.html new file mode 100644 index 000000000..038fc575c --- /dev/null +++ b/doc/1.7_rc1/dom/element/removeclassname/index.html @@ -0,0 +1,314 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.removeClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.removeClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element.removeClassName(element, className) → Element
    + + +

    Removes CSS class className from element.

    + +
    Examples
    + +

    Assuming this HTML:

    + +
    <div id="mutsu" class="apple fruit food"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').removeClassName('food');
    +// -> Element
    + $('mutsu').classNames;
    +// -> 'apple fruit'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/replace/index.html b/doc/1.7_rc1/dom/element/replace/index.html new file mode 100644 index 000000000..2d7ef8ca5 --- /dev/null +++ b/doc/1.7_rc1/dom/element/replace/index.html @@ -0,0 +1,366 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.replace + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.replace +

    + + + + +
    +
    +
    +
    +
    +
    Element.replace(element[, newContent]) → Element
    + + +

    Replaces element itself with newContent and returns element.

    + +

    Keep in mind that this method returns the element that has just been +removed — not the element that took its place.

    + +

    newContent can be either plain text, an HTML snippet or any JavaScript +object which has a toString() method.

    + +

    If newContent contains any <script> tags, these will be evaluated +after element has been replaced (Element.replace internally calls +String#evalScripts).

    + +

    Note that if no argument is provided, Element.replace will simply +clear element of its content. However, using Element.remove to do so +is both faster and more standard compliant.

    + +
    Examples
    + +
    <div id="food">
    +  <div id="fruits">
    +    <p id="first">Kiwi, banana <em>and</em> apple.</p>
    +  </div>
    +</div>
    +
    +
    + +

    Passing an HTML snippet:

    + +
    $('first').replace('<ul id="favorite"><li>kiwi</li><li>banana</li><li>apple</li></ul>');
    +// -> Element (p#first)
    + $('fruits').innerHTML;
    +// -> '<ul id="favorite"><li>kiwi</li><li>banana</li><li>apple</li></ul>'
    +
    +
    + +

    Again, with a <script> tag thrown in:

    + +
    $('favorite').replace('<p id="still-first">Melon, oranges <em>and</em> grapes.</p><script>alert("removed!")</script>');
    +// -> Element (ul#favorite) and prints "removed!" in an alert dialog.
    + $('fruits').innerHTML;
    +// -> '<p id="still-first">Melon, oranges <em>and</em> grapes.</p>'
    +
    +
    + +

    With plain text:

    + +
    $('still-first').replace('Melon, oranges and grapes.');
    +// -> Element (p#still-first)
    + $('fruits').innerHTML;
    +// -> 'Melon, oranges and grapes.'
    +
    +
    + +

    Finally, relying on the toString() method:

    + +
    $('fruits').replace(123);
    +// -> Element
    + $('food').innerHTML;
    +// -> '123'
    +
    +
    + +
    Warning
    + +

    Using Element.replace as an instance method (e.g., +$('foo').replace('<p>Bar</p>')) causes errors in Opera 9 when used on +input elements. The replace property is reserved on input elements +as part of Web Forms 2. +As a workaround, use the generic version instead +(Element.replace('foo', '<p>Bar</p>')).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/retrieve/index.html b/doc/1.7_rc1/dom/element/retrieve/index.html new file mode 100644 index 000000000..f1eafe03d --- /dev/null +++ b/doc/1.7_rc1/dom/element/retrieve/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.retrieve + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.retrieve +

    + + + + +
    +
    +
    +
    +
    +
    Element.retrieve(element, key[, defaultValue]) → ?
    + + +

    Retrieves custom metadata set on element with Element.store.

    + +

    If the value is undefined and defaultValue is given, it will be +stored on the element as its new value for that key, then returned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/scrollto/index.html b/doc/1.7_rc1/dom/element/scrollto/index.html new file mode 100644 index 000000000..588abf9d1 --- /dev/null +++ b/doc/1.7_rc1/dom/element/scrollto/index.html @@ -0,0 +1,308 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.scrollTo + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.scrollTo +

    + + + + +
    +
    +
    +
    +
    +
    Element.scrollTo(element) → Element
    + + +

    Scrolls the window so that element appears at the top of the viewport.

    + +

    This has a similar effect than what would be achieved using +HTML anchors +(except the browser's history is not modified).

    + +
    Example
    + +
    $(element).scrollTo();
    +// -> Element
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/select/index.html b/doc/1.7_rc1/dom/element/select/index.html new file mode 100644 index 000000000..5b4f8f7f8 --- /dev/null +++ b/doc/1.7_rc1/dom/element/select/index.html @@ -0,0 +1,356 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.select +

    + + + + +
    +
    +
    +
    +
    +
    Element.select(element, expression...) → [Element…]
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Takes an arbitrary number of CSS selectors and returns an array of +descendants of element that match any of them.

    + +

    This method is very similar to $$ but can be used within the context +of one element, rather than the whole document. The supported CSS syntax +is identical, so please refer to the $$ docs for details.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3 title="yummy!">Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious" title="yummy!" >Golden Delicious</li>
    +      <li id="mutsu" title="yummy!">Mutsu</li>
    +      <li id="mcintosh">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('apples').select('[title="yummy!"]');
    +// -> [h3, li#golden-delicious, li#mutsu]
    + $('apples').select( 'p#saying', 'li[title="yummy!"]');
    +// -> [li#golden-delicious, li#mutsu,  p#saying]
    + $('apples').select('[title="disgusting!"]');
    +// -> []
    +
    +
    + +
    Tip
    + +

    Element.select can be used as a pleasant alternative to the native +method getElementsByTagName:

    + +
    var nodes  = $A(someUL.getElementsByTagName('li')).map(Element.extend);
    +var nodes2 = someUL.select('li');
    +
    +
    + +

    In the first example, you must explicitly convert the result set to an +Array (so that Prototype's Enumerable methods can be used) and +must manually call Element.extend on each node (so that custom +instance methods can be used on the nodes). Element.select takes care +of both concerns on its own.

    + +

    If you're using 1.6 or above (and the performance optimizations therein), +the speed difference between these two examples is negligible.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/setopacity/index.html b/doc/1.7_rc1/dom/element/setopacity/index.html new file mode 100644 index 000000000..066af0c00 --- /dev/null +++ b/doc/1.7_rc1/dom/element/setopacity/index.html @@ -0,0 +1,313 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.setOpacity + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.setOpacity +

    + + + + +
    +
    +
    +
    +
    +
    Element.setOpacity(element, opacity) → [Element…]
    + + +

    Sets the visual opacity of an element while working around inconsistencies +in various browsers. The opacity argument should be a floating point +number, where the value of 0 is fully transparent and 1 is fully opaque.

    + +

    Element.setStyle method uses Element.setOpacity internally when needed.

    + +
    Examples
    + +
    var element = $('myelement');
    +// set to 50% transparency
    +element.setOpacity(0.5);
    + // these are equivalent, but allow for setting more than
    +// one CSS property at once:
    +element.setStyle({ opacity: 0.5 });
    +element.setStyle("opacity: 0.5");
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/setstyle/index.html b/doc/1.7_rc1/dom/element/setstyle/index.html new file mode 100644 index 000000000..bd8fa9c33 --- /dev/null +++ b/doc/1.7_rc1/dom/element/setstyle/index.html @@ -0,0 +1,334 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.setStyle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.setStyle +

    + + + + +
    +
    +
    +
    +
    +
    Element.setStyle(element, styles) → Element
    + + +

    Modifies element's CSS style properties. Styles are passed as a hash of +property-value pairs in which the properties are specified in their +camelized form.

    + +
    Examples
    + +
    $(element).setStyle({
    +  backgroundColor: '#900',
    +  fontSize: '12px'
    +});
    +// -> Element
    +
    +
    + +
    Notes
    + +

    The method transparently deals with browser inconsistencies for float +(however, as float is a reserved keyword, you must either escape it or +use cssFloat instead) and opacity (which accepts values between 0 +-fully transparent- and 1 -fully opaque-). You can safely use either of +the following across all browsers:

    + +
    $(element).setStyle({
    +  cssFloat: 'left',
    +  opacity: 0.5
    +});
    +// -> Element
    + $(element).setStyle({
    +  'float': 'left', // notice how float is surrounded by single quotes
    +  opacity: 0.5
    +});
    +// -> Element
    +
    +
    + +

    Not all CSS shorthand properties are supported. You may only use the CSS +properties described in the +Document Object Model (DOM) Level 2 Style Specification.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/show/index.html b/doc/1.7_rc1/dom/element/show/index.html new file mode 100644 index 000000000..22e8ae79b --- /dev/null +++ b/doc/1.7_rc1/dom/element/show/index.html @@ -0,0 +1,339 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.show + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.show +

    + + + + +
    +
    +
    +
    +
    +
    Element.show(element) → Element
    + + +

    Removes display: none on element. Returns element.

    + +
    Examples
    + +

    Show a single element:

    + +
    <div id="error-message" style="display:none;"></div>
    + $('error-message').show();
    +// -> Element (and displays div#error-message)
    +
    +
    + +

    Show multiple elements using Enumerable#each:

    + +
    ['content', 'navigation', 'footer'].each(Element.show);
    +// -> ['content', 'navigation', 'footer']
    +
    +
    + +

    Show multiple elements using Enumerable#invoke:

    + +
    $('content', 'navigation', 'footer').invoke('show');
    +// -> [Element, Element, Element]
    +
    +
    + +
    Notes
    + +

    Element.show cannot display elements hidden via CSS stylesheets. +Note that this is not a Prototype limitation but a consequence of how the +CSS display property works.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    + $('hidden-by-css').show(); // DOES NOT WORK!
    +// -> Element (div#error-message is still hidden!)
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/siblings/index.html b/doc/1.7_rc1/dom/element/siblings/index.html new file mode 100644 index 000000000..d06c999b8 --- /dev/null +++ b/doc/1.7_rc1/dom/element/siblings/index.html @@ -0,0 +1,326 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.siblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.siblings +

    + + + + +
    +
    +
    +
    +
    +
    Element.siblings(element) → [Element…]
    + + +

    Collects all of element's siblings and returns them as an Array of +elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the head and body elements are siblings (their parent is the html +element).

    + +

    The returned Array reflects the siblings' order in the document (e.g. +an index of 0 refers to element's topmost sibling).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mutsu').siblings();
    +// -> [li#golden-delicious, li#mcintosh, li#ida-red]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/stopobserving/index.html b/doc/1.7_rc1/dom/element/stopobserving/index.html new file mode 100644 index 000000000..689379171 --- /dev/null +++ b/doc/1.7_rc1/dom/element/stopobserving/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.stopObserving + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.stopObserving +

    + + + + +
    +
    +
    +
    +
    +
    Element.stopObserving(element[, eventName[, handler]]) → Element
    + + +

    See Event.stopObserving.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/store/index.html b/doc/1.7_rc1/dom/element/store/index.html new file mode 100644 index 000000000..02186b758 --- /dev/null +++ b/doc/1.7_rc1/dom/element/store/index.html @@ -0,0 +1,299 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.store + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.store +

    + + + + +
    +
    +
    +
    +
    +
    Element.store(element, key, value) → Element
    + + +

    Stores a key/value pair of custom metadata on the element.

    + +

    The metadata can later be retrieved with Element.retrieve.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/toggle/index.html b/doc/1.7_rc1/dom/element/toggle/index.html new file mode 100644 index 000000000..bac7757d4 --- /dev/null +++ b/doc/1.7_rc1/dom/element/toggle/index.html @@ -0,0 +1,340 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.toggle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.toggle +

    + + + + +
    +
    +
    +
    +
    +
    Element.toggle(element) → Element
    + + +

    Toggles the visibility of element. Returns element.

    + +
    Examples
    + +
    <div id="welcome-message"></div>
    +<div id="error-message" style="display:none;"></div>
    + $('welcome-message').toggle();
    +// -> Element (and hides div#welcome-message)
    + $('error-message').toggle();
    +// -> Element (and displays div#error-message)
    +
    +
    + +

    Toggle multiple elements using Enumerable#each:

    + +
    ['error-message', 'welcome-message'].each(Element.toggle);
    +// -> ['error-message', 'welcome-message']
    +
    +
    + +

    Toggle multiple elements using Enumerable#invoke:

    + +
    $('error-message', 'welcome-message').invoke('toggle');
    +// -> [Element, Element]
    +
    +
    + +
    Notes
    + +

    Element.toggle cannot display elements hidden via CSS stylesheets. +Note that this is not a Prototype limitation but a consequence of how the +CSS display property works.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    + $('hidden-by-css').toggle(); // WONT' WORK!
    +// -> Element (div#hidden-by-css is still hidden!)
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/toggleclassname/index.html b/doc/1.7_rc1/dom/element/toggleclassname/index.html new file mode 100644 index 000000000..709fd0035 --- /dev/null +++ b/doc/1.7_rc1/dom/element/toggleclassname/index.html @@ -0,0 +1,314 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.toggleClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.toggleClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element.toggleClassName(element, className) → Element
    + + +

    Toggles the presence of CSS class className on element.

    + +
    Examples
    + +
    <div id="mutsu" class="apple"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').hasClassName('fruit');
    +// -> false
    + $('mutsu').toggleClassName('fruit');
    +// -> element
    + $('mutsu').hasClassName('fruit');
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/undoclipping/index.html b/doc/1.7_rc1/dom/element/undoclipping/index.html new file mode 100644 index 000000000..3e8fd0fa7 --- /dev/null +++ b/doc/1.7_rc1/dom/element/undoclipping/index.html @@ -0,0 +1,341 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.undoClipping + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.undoClipping +

    + + + + +
    +
    +
    +
    +
    +
    Element.undoClipping(element) → Element
    + + +

    Sets element's CSS overflow property back to the value it had +before Element.makeClipping was applied.

    + +
    Example
    + +
    <div id="framer">
    +  <img src="/assets/2007/1/14/chairs.jpg" alt="example" />
    +</div>
    +
    +
    + +

    Then:

    + +
    $('framer').undoClipping();
    +// -> Element (and sets the CSS overflow property to its original value).
    +
    +
    + +

    Another example:

    + +
    <a id="clipper" href="#">Click me to try it out.</a>
    + <div id="framer">
    +  <img src="/assets/2007/2/24/chairs_1.jpg" alt="example" />
    +</div>
    + <script type="text/javascript" charset="utf-8">
    +  var Example = {
    +    clip: function(){
    +      $('clipper').update('undo clipping!');
    +      $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +    },
    +    unClip: function(){
    +      $('clipper').update('clip!');
    +      $('framer').undoClipping();
    +    },
    +    toggleClip: function(event){
    +      if($('clipper').innerHTML == 'clip!') Example.clip();
    +      else Example.unClip();
    +      Event.stop(event);
    +    }
    +  };
    +  $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +  Event.observe('clipper', 'click', Example.toggleClip);
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/undopositioned/index.html b/doc/1.7_rc1/dom/element/undopositioned/index.html new file mode 100644 index 000000000..3c573ed80 --- /dev/null +++ b/doc/1.7_rc1/dom/element/undopositioned/index.html @@ -0,0 +1,302 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.undoPositioned + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.undoPositioned +

    + + + + +
    +
    +
    +
    +
    +
    Element.undoPositioned(element) → Element
    + + +

    Sets element back to the state it was in before +Element.makePositioned was applied to it.

    + +

    element's absolutely positioned children will now have their positions +set relatively to element's nearest ancestor with a CSS position of +'absolute', 'relative' or 'fixed'.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/up/index.html b/doc/1.7_rc1/dom/element/up/index.html new file mode 100644 index 000000000..83f05868b --- /dev/null +++ b/doc/1.7_rc1/dom/element/up/index.html @@ -0,0 +1,413 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.up + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.up +

    + + + + +
    +
    +
    +
    +
    +
    Element.up(element[, expression[, index = 0]]) → Element
    Element.up(element[, index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first ancestor (or the Nth ancestor, if index +is specified) that matches expression. If no expression is +provided, all ancestors are considered. If no ancestor matches these +criteria, undefined is returned.

    + +
    More information
    + +

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

    + +

    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 +(see Element.extended) allowing chaining:

    + +
    $(element).up(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's first ancestor is returned (this +is similar to calling parentNode except Element.up returns an already +extended element.

    + +

    If index is defined, element's corresponding ancestor is returned. +(This is equivalent to selecting an element from the array of elements +returned by the method Element.ancestors). Note that the first element +has an index of 0.

    + +

    If expression is defined, Element.up will return the first ancestor +that matches it.

    + +

    If both expression and index are defined, Element.up will collect +all the ancestors matching the given CSS expression and will return the +one at the specified index.

    + +

    In all of the above cases, if no descendant is found, undefined +will be returned.

    + +

    Examples

    + +
    <html>
    +  [...]
    +  <body>
    +    <ul id="fruits">
    +      <li id="apples" class="keeps-the-doctor-away">
    +        <ul>
    +          <li id="golden-delicious">Golden Delicious</li>
    +          <li id="mutsu" class="yummy">Mutsu</li>
    +          <li id="mcintosh" class="yummy">McIntosh</li>
    +          <li id="ida-red">Ida Red</li>
    +        </ul>
    +      </li>
    +    </ul>
    +  </body>
    +</html>
    +
    +
    + +

    Get the first ancestor of "#fruites":

    + +
    $('fruits').up();
    +// or:
    +$('fruits').up(0);
    +// -> body
    +
    +
    + +

    Get the third ancestor of "#mutsu":

    + +
    $('mutsu').up(2);
    +// -> ul#fruits
    +
    +
    + +

    Get the first ancestor of "#mutsu" with the node name "li":

    + +
    $('mutsu').up('li');
    +// -> li#apples
    +
    +
    + +

    Get the first ancestor of "#mutsu" with the class name +"keeps-the-doctor-away":

    + +
    $('mutsu').up('.keeps-the-doctor-away');
    +// -> li#apples
    +
    +
    + +

    Get the second ancestor of "#mutsu" with the node name "ul":

    + +
    $('mutsu').up('ul', 1);
    +// -> ul#fruits
    +
    +
    + +

    Try to get the first ancestor of "#mutsu" with the node name "div":

    + +
    $('mutsu').up('div');
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/update/index.html b/doc/1.7_rc1/dom/element/update/index.html new file mode 100644 index 000000000..c9b5e7dd5 --- /dev/null +++ b/doc/1.7_rc1/dom/element/update/index.html @@ -0,0 +1,391 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.update + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.update +

    + + + + +
    +
    +
    +
    +
    +
    Element.update(element[, newContent]) → Element
    + + +

    Replaces the content of element with the newContent argument and +returns element.

    + +

    newContent may be in any of these forms:

    + +
      +
    • String: A string of HTML to be parsed and rendered
    • +
    • Element: An Element instance to insert
    • +
    • ...any object with a toElement method: The method is called and the resulting element used
    • +
    • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
    • +
    + +

    If newContent is omitted, the element's content is blanked out (i.e., +replaced with an empty string).

    + +

    If newContent is a string and contains one or more inline <script> +tags, the scripts are scheduled to be evaluated after a very brief pause +(using Function#defer) to allow the browser to finish updating the +DOM. Note that the scripts are evaluated in the scope of +String#evalScripts, not in the global scope, which has important +ramifications for your vars and functions. +See String#evalScripts for details.

    + +

    Note that this method allows seamless content update of table related +elements in Internet Explorer 6 and beyond.

    + +
    Examples
    + +
    <div id="fruits">carrot, eggplant and cucumber</div>
    +
    +
    + +

    Passing a regular string:

    + +
    $('fruits').update('kiwi, banana and apple');
    +// -> Element
    +$('fruits').innerHTML;
    +// -> 'kiwi, banana and apple'
    +
    +
    + +

    Clearing the element's content:

    + +
    $('fruits').update();
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '' (an empty string)
    +
    +
    + +

    And now inserting an HTML snippet:

    + +
    $('fruits').update('<p>Kiwi, banana <em>and</em> apple.</p>');
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '<p>Kiwi, banana <em>and</em> apple.</p>'
    +
    +
    + +

    ... with a <script> tag thrown in:

    + +
    $('fruits').update('<p>Kiwi, banana <em>and</em> apple.</p><script>alert("updated!")</script>');
    +// -> Element (and prints "updated!" in an alert dialog).
    +$('fruits').innerHTML;
    +// -> '<p>Kiwi, banana <em>and</em> apple.</p>'
    +
    +
    + +

    Relying on the toString() method:

    + +
    $('fruits').update(123);
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '123'
    +
    +
    + +

    Finally, you can do some pretty funky stuff by defining your own +toString() method on your custom objects:

    + +
    var Fruit = Class.create({
    +  initialize: function(fruit){
    +    this.fruit = fruit;
    +  },
    +  toString: function(){
    +    return 'I am a fruit and my name is "' + this.fruit + '".';
    +  }
    +});
    +var apple = new Fruit('apple');
    + $('fruits').update(apple);
    +$('fruits').innerHTML;
    +// -> 'I am a fruit and my name is "apple".'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/viewportoffset/index.html b/doc/1.7_rc1/dom/element/viewportoffset/index.html new file mode 100644 index 000000000..360baa1ec --- /dev/null +++ b/doc/1.7_rc1/dom/element/viewportoffset/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.viewportOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.viewportOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element.viewportOffset(element) → Array
    + + +

    Returns the X/Y coordinates of element relative to the viewport.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/visible/index.html b/doc/1.7_rc1/dom/element/visible/index.html new file mode 100644 index 000000000..fe72e1c9f --- /dev/null +++ b/doc/1.7_rc1/dom/element/visible/index.html @@ -0,0 +1,336 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.visible + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.visible +

    + + + + +
    +
    +
    +
    +
    +
    Element.visible(element) → Boolean
    + + +

    Tells whether element is visible (i.e., whether its inline display +CSS property is set to none.

    + +
    Examples
    + +
    <div id="visible"></div>
    +<div id="hidden" style="display: none;"></div>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('visible').visible();
    +// -> true
    + $('hidden').visible();
    +// -> false
    +
    +
    + +
    Notes
    + +

    Styles applied via a CSS stylesheet are not taken into consideration. +Note that this is not a Prototype limitation, it is a CSS limitation.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('hidden-by-css').visible();
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/wrap/index.html b/doc/1.7_rc1/dom/element/wrap/index.html new file mode 100644 index 000000000..6292077e7 --- /dev/null +++ b/doc/1.7_rc1/dom/element/wrap/index.html @@ -0,0 +1,370 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.wrap + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.wrap +

    + + + + +
    +
    +
    +
    +
    +
    Element.wrap(element, wrapper[, attributes]) → Element
    +
      +
    • + wrapper + (Element | String) + – An element to wrap element inside, or else a string representing the tag name of an element to be created. +
    • +
    • + attributes + (Object) + – A set of attributes to apply to the wrapper element. Refer to the Element constructor for usage. +
    • +
    + + +

    Wraps an element inside another, then returns the wrapper.

    + +

    If the given element exists on the page, Element.wrap will wrap it in +place — its position will remain the same.

    + +

    The wrapper argument can be either an existing Element _or_ a +string representing the tag name of an element to be created. The optional +attributes argument can contain a list of attribute/value pairs that +will be set on the wrapper using Element.writeAttribute.

    + +
    Examples
    + +

    Original HTML:

    + +
    <table id="data">
    +  <tr>
    +    <th>Foo</th>
    +    <th>Bar</th>
    +  </tr>
    +  <tr>
    +    <td>1</td>
    +    <td>2</td>
    +  </tr>
    +</table>
    +
    +
    + +

    JavaScript:

    + +
    // approach 1:
    +var div = new Element('div', { 'class': 'table-wrapper' });
    +$('data').wrap(div);
    + // approach 2:
    +$('data').wrap('div', { 'class': 'table-wrapper' });
    + // Both examples are equivalent &mdash; they return the DIV.
    +
    +
    + +

    Resulting HTML:

    + +
    <div class="table-wrapper">
    +  <table id="data">
    +    <tr>
    +      <th>Foo</th>
    +      <th>Bar</th>
    +    </tr>
    +    <tr>
    +      <td>1</td>
    +      <td>2</td>
    +    </tr>
    +  </table>
    +</div>
    +
    +
    + +
    Warning
    + +

    Using Element.wrap as an instance method (e.g., $('foo').wrap('p')) +causes errors in Internet Explorer when used on textarea elements. The +wrap property is reserved on textarea's as a proprietary extension to +HTML. As a workaround, use the generic version instead +(Element.wrap('foo', 'p')).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/element/writeattribute/index.html b/doc/1.7_rc1/dom/element/writeattribute/index.html new file mode 100644 index 000000000..c7330831b --- /dev/null +++ b/doc/1.7_rc1/dom/element/writeattribute/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.writeAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.writeAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element.writeAttribute(element, attribute[, value = true]) → Element
    Element.writeAttribute(element, attributes) → Element
    + + +

    Adds, specifies or removes attributes passed as either a hash or a +name/value pair.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/element/index.html b/doc/1.7_rc1/dom/event/element/index.html new file mode 100644 index 000000000..845c6a09d --- /dev/null +++ b/doc/1.7_rc1/dom/event/element/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.element + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Event.element +

    + + + + +
    +
    +
    +
    +
    +
    Event.element(event) → Element
    +
      +
    • + event + (Event) + – An Event object +
    • +
    + + +

    Returns the DOM element on which the event occurred. This method +is deprecated, use Event.findElement instead.

    + +
    Example
    + +

    Here's a simple bit of code which hides any paragraph when directly clicked.

    + +
    document.observe('click', function(event) {
    +  var element = Event.element(event);
    +  if ('P' == element.tagName)
    +    element.hide();
    +});
    +
    +
    + +
    See also
    + +

    There is a subtle distinction between this function and +Event.findElement.

    + +
    Note for Prototype 1.5.0
    + +

    Note that prior to version 1.5.1, if the browser does not support +native DOM extensions (see the Element section for further details), +the element returned by Event.element might very well +not be extended. If you intend to use methods from Element.Methods +on it, you need to wrap the call in the $ function like so:

    + +
    document.observe('click', function(event) {
    +  var element = $(Event.element(event));
    +  // ...
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/extend/index.html b/doc/1.7_rc1/dom/event/extend/index.html new file mode 100644 index 000000000..3a0144d6c --- /dev/null +++ b/doc/1.7_rc1/dom/event/extend/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.extend +

    + + + + +
    +
    +
    +
    +
    +
    Event.extend(event) → Event
    + + +

    Extends event with all of the methods contained in Event.Methods.

    + +

    Note that all events inside handlers that were registered using +Event.observe or Element.observe will be extended automatically.

    + +

    You need only call Event.extend manually if you register a handler a +different way (e.g., the onclick attribute). We really can't encourage +that sort of thing, though.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/findelement/index.html b/doc/1.7_rc1/dom/event/findelement/index.html new file mode 100644 index 000000000..ae6db290a --- /dev/null +++ b/doc/1.7_rc1/dom/event/findelement/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.findElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.findElement +

    + + + + +
    +
    +
    +
    +
    +
    Event.findElement(event[, expression]) → Element
    +
      +
    • + event + (Event) + – An Event object +
    • +
    • + expression + (String) + – An optional CSS selector +
    • +
    + + +

    Returns the first DOM element that matches a given CSS selector — +starting with the element on which the event occurred, then moving up +its ancestor chain. If expression is not given, the element which fired +the event is returned.

    + +

    *If no matching element is found, the document itself (HTMLDocument node) +is returned.*

    + +
    Example
    + +

    Here's a simple code that lets you click everywhere on the page and hides +the closest-fitting paragraph around your click (if any).

    + +
    document.observe('click', function(event) {
    +  var element = Event.findElement(event, 'p');
    +  if (element != document)
    +    $(element).hide();
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/fire/index.html b/doc/1.7_rc1/dom/event/fire/index.html new file mode 100644 index 000000000..718a2a9bc --- /dev/null +++ b/doc/1.7_rc1/dom/event/fire/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.fire + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.fire +

    + + + + +
    +
    +
    +
    +
    +
    Event.fire(element, eventName[, memo[, bubble = true]]) → Event
    +
      +
    • + memo + (?) + – Metadata for the event. Will be accessible through the event's memo property. +
    • +
    • + bubble + (Boolean) + – Whether the event will bubble. +
    • +
    + + +

    Fires a custom event of name eventName with element as its target.

    + +

    Custom events must include a colon (:) in their names.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/handler/index.html b/doc/1.7_rc1/dom/event/handler/index.html new file mode 100644 index 000000000..2e12a7611 --- /dev/null +++ b/doc/1.7_rc1/dom/event/handler/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.Handler + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Event.Handler +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Creates an observer on an element that listens for a particular event on +that element's descendants, optionally filtering by a CSS selector.

    + +

    This class simplifies the common "event delegation" pattern, in which one +avoids adding an observer to a number of individual elements and instead +listens on a common ancestor element.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance properties

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/handler/new/index.html b/doc/1.7_rc1/dom/event/handler/new/index.html new file mode 100644 index 000000000..80bc4b9d1 --- /dev/null +++ b/doc/1.7_rc1/dom/event/handler/new/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | new Event.Handler + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Event.Handler +

    + + + + +
    +
    +
    +
    +
    +
    new(element, eventName[, selector], callback)
    +
      +
    • + element + (Element) + – The element to listen on. +
    • +
    • + eventName + (String) + – An event to listen for. Can be a standard browser event or a custom event. +
    • +
    • + selector + (String) + – A CSS selector. If specified, will call callback only when it can find an element that matches selector somewhere in the ancestor chain between the event's target element and the given element. +
    • +
    • + callback + (Function) + – The event handler function. Should expect two arguments: the event object and the element that received the event. (If selector was given, this element will be the one that satisfies the criteria described just above; if not, it will be the one specified in the element argument). +
    • +
    + + +

    Instantiates an Event.Handler. Will not begin observing until +Event.Handler#start is called.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/handler/prototype/start/index.html b/doc/1.7_rc1/dom/event/handler/prototype/start/index.html new file mode 100644 index 000000000..f59c2f2d2 --- /dev/null +++ b/doc/1.7_rc1/dom/event/handler/prototype/start/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.Handler#start + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Event.Handler#start +

    + + + + +
    +
    +
    +
    +
    +
    Event.Handler#start → Event.Handler
    + + +

    Starts listening for events. Returns itself.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/handler/prototype/stop/index.html b/doc/1.7_rc1/dom/event/handler/prototype/stop/index.html new file mode 100644 index 000000000..c7310719c --- /dev/null +++ b/doc/1.7_rc1/dom/event/handler/prototype/stop/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.Handler#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Event.Handler#stop +

    + + + + +
    +
    +
    +
    +
    +
    Event.Handler#stop → Event.Handler
    + + +

    Stops listening for events. Returns itself.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/index.html b/doc/1.7_rc1/dom/event/index.html new file mode 100644 index 000000000..034e7971d --- /dev/null +++ b/doc/1.7_rc1/dom/event/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Event + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Event +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    The namespace for Prototype's event system.

    + +
    Events: a fine mess
    + +

    Event management is one of the really sore spots of cross-browser +scripting.

    + +

    True, the prevalent issue is: everybody does it the W3C way, and MSIE +does it another way altogether. But there are quite a few subtler, +sneakier issues here and there waiting to bite your ankle — such as the +keypress/keydown issue with KHTML-based browsers (Konqueror and +Safari). Also, MSIE has a tendency to leak memory when it comes to +discarding event handlers.

    + +
    Prototype to the rescue
    + +

    Of course, Prototype smooths it over so well you'll forget these +troubles even exist. Enter the Event namespace. It is replete with +methods that help to normalize the information reported by events across +browsers.

    + +

    Event also provides a standardized list of key codes you can use with +keyboard-related events, including KEY_BACKSPACE, KEY_TAB, +KEY_RETURN, KEY_ESC, KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN, +KEY_DELETE, KEY_HOME, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN and +KEY_INSERT.

    + +

    The functions you're most likely to use a lot are Event.observe, +Event.element and Event.stop. If your web app uses custom events, +you'll also get a lot of mileage out of Event.fire.

    + +
    Instance methods on event objects
    + +

    As of Prototype 1.6, all methods on the Event object are now also +available as instance methods on the event object itself:

    + +

    Before

    + +
    $('foo').observe('click', respondToClick);
    + function respondToClick(event) {
    +  var element = Event.element(event);
    +  element.addClassName('active');
    +}
    +
    +
    + +

    After

    + +
    $('foo').observe('click', respondToClick);
    + function respondToClick(event) {
    +  var element = event.element();
    +  element.addClassName('active');
    +}
    +
    +
    + +

    These methods are added to the event object through Event.extend, +in the same way that Element methods are added to DOM nodes through +Element.extend. Events are extended automatically when handlers are +registered with Prototype's Event.observe method; if you're using a +different method of event registration, for whatever reason,you'll need to +extend these events manually with Event.extend.

    +
    +
    + + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Event.Handler

      + +

      Creates an observer on an element that listens for a particular event on +that element's descendants, optionally filtering by a CSS selector.

      +
    • +
    +
    +
    + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/isleftclick/index.html b/doc/1.7_rc1/dom/event/isleftclick/index.html new file mode 100644 index 000000000..5b3d8ba0f --- /dev/null +++ b/doc/1.7_rc1/dom/event/isleftclick/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.isLeftClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.isLeftClick +

    + + + + +
    +
    +
    +
    +
    +
    Event.isLeftClick(event) → Boolean
    + + +

    Determines whether a button-related mouse event involved the left +mouse button.

    + +

    Keep in mind that the "left" mouse button is actually the "primary" mouse +button. When a mouse is in left-handed mode, the browser will report +clicks of the right button as "left-clicks."

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/ismiddleclick/index.html b/doc/1.7_rc1/dom/event/ismiddleclick/index.html new file mode 100644 index 000000000..3a9882974 --- /dev/null +++ b/doc/1.7_rc1/dom/event/ismiddleclick/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.isMiddleClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.isMiddleClick +

    + + + + +
    +
    +
    +
    +
    +
    Event.isMiddleClick(event) → Boolean
    + + +

    Determines whether a button-related mouse event involved the middle +mouse button.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/isrightclick/index.html b/doc/1.7_rc1/dom/event/isrightclick/index.html new file mode 100644 index 000000000..d61bffb39 --- /dev/null +++ b/doc/1.7_rc1/dom/event/isrightclick/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.isRightClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.isRightClick +

    + + + + +
    +
    +
    +
    +
    +
    Event.isRightClick(event) → Boolean
    + + +

    Determines whether a button-related mouse event involved the right +mouse button.

    + +

    Keep in mind that the "left" mouse button is actually the "secondary" +mouse button. When a mouse is in left-handed mode, the browser will +report clicks of the left button as "left-clicks."

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/observe/index.html b/doc/1.7_rc1/dom/event/observe/index.html new file mode 100644 index 000000000..d2737134e --- /dev/null +++ b/doc/1.7_rc1/dom/event/observe/index.html @@ -0,0 +1,338 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.observe + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.observe +

    + + + + +
    +
    +
    +
    +
    +
    Event.observe(element, eventName, handler) → Element
    +
      +
    • + element + (Element | String) + – The DOM element to observe, or its ID. +
    • +
    • + eventName + (String) + – The name of the event, in all lower case, without the "on" prefix — e.g., "click" (not "onclick"). +
    • +
    • + handler + (Function) + – The function to call when the event occurs. +
    • +
    + + +

    Registers an event handler on a DOM element. Aliased as Element#observe.

    + +

    Event.observe smooths out a variety of differences between browsers +and provides some handy additional features as well. Key features in brief:

    + +
      +
    • Several handlers can be registered for the same event on the same element.
    • +
    • Prototype figures out whether to use addEventListener (W3C standard) or +attachEvent (MSIE); you don't have to worry about it.
    • +
    • The handler is passed an extended Event object (even on MSIE).
    • +
    • The handler's context (this value) is set to the extended element +being observed (even if the event actually occurred on a descendent +element and bubbled up).
    • +
    • Prototype handles cleaning up the handler when leaving the page +(important for MSIE memory leak prevention).
    • +
    • Event.observe makes it possible to stop observing the event easily +via Event.stopObserving.
    • +
    • Adds support for mouseenter / mouseleave events in all browsers.
    • +
    + +

    Although you can use Event.observe directly and there are times when +that's the most convenient or direct way, it's more common to use its +alias Element#observe. These two statements have the same effect:

    + +
    Event.observe('foo', 'click', myHandler);
    +$('foo').observe('click', myHandler);
    +
    +
    + +

    The examples in this documentation use the Element#observe form.

    + +
    The Handler
    + +

    Signature:

    + +
    function handler(event) {
    +  // `this` = the element being observed
    +}
    +
    +
    + +

    So for example, this will turn the background of the element 'foo' blue +when it's clicked:

    + +
    $('foo').observe('click', function(event) {
    +  this.setStyle({backgroundColor: 'blue'});
    +});
    +
    +
    + +

    Note that we used this to refer to the element, and that we received the +event object as a parameter (even on MSIE).

    + +
    It's All About Timing
    + +

    One of the most common errors trying to observe events is trying to do it +before the element exists in the DOM. Don't try to observe elements until +after the dom:loaded event or window load event +has been fired.

    + +
    Preventing the Default Event Action and Bubbling
    + +

    If we want to stop the event (e.g., prevent its default action and stop it +bubbling), we can do so with the extended event object's Event#stop +method:

    + +
    $('foo').observe('click', function(event) {
    +  event.stop();
    +});
    +
    +
    + +
    Finding the Element Where the Event Occurred
    + +

    Since most events bubble from descendant elements up through the hierarchy +until they're handled, we can observe an event on a container rather than +individual elements within the container. This is sometimes called "event +delegation". It's particularly handy for tables:

    + +
    <table id='records'>
    +  <thead>
    +    <tr><th colspan='2'>No record clicked</th></tr>
    +  </thead>
    +  <tbody>
    +    <tr data-recnum='1'><td>1</td><td>First record</td></tr>
    +    <tr data-recnum='2'><td>2</td><td>Second record</td></tr>
    +    <tr data-recnum='3'><td>3</td><td>Third record</td></tr>
    +  </tbody>
    +</table>
    +
    +
    + +

    Instead of observing each cell or row, we can simply observe the table:

    + +
    $('records').observe('click', function(event) {
    +  var clickedRow = event.findElement('tr');
    +  if (clickedRow) {
    +    this.down('th').update("You clicked record #" + clickedRow.readAttribute("data-recnum"));
    +  }
    +});
    +
    +
    + +

    When any row in the table is clicked, we update the table's first header +cell saying which record was clicked. Event#findElement finds the row +that was clicked, and this refers to the table we were observing.

    + +
    Stopping Observing the Event
    + +

    If we don't need to observe the event anymore, we can stop observing it +with Event.stopObserving or its Element#stopObserving alias.

    + +
    Using an Instance Method as a Handler
    + +

    If we want to use an instance method as a handler, we will probably want +to use Function#bind to set the handler's context; otherwise, the +context will be lost and this won't mean what we expect it to mean +within the handler function. E.g.:

    + +
    var MyClass = Class.create({
    +  initialize: function(name, element) {
    +    this.name = name;
    +    element = $(element);
    +    if (element) {
    +      element.observe(this.handleClick.bind(this));
    +    }
    +  },
    +  handleClick: function(event) {
    +    alert("My name is " + this.name);
    +  },
    +});
    +
    +
    + +

    Without the Function#bind, when handleClick was triggered by the +event, this wouldn't refer to the instance and so the alert wouldn't +show the name. Because we used Function#bind, it works correctly. See +Function#bind for details. There's also Function#bindAsEventListener, +which is handy for certain very specific situations. (Normally, +Function#bind is all you need.)

    + +
    Side Notes
    + +

    Although Prototype smooths out most of the differences between browsers, +the fundamental behavior of a browser implementation isn't changed. For +example, the timing of the change or blur events varies a bit from +browser to browser.

    + +
    Changes in 1.6.x
    + +

    Prior to Prototype 1.6, Event.observe supported a fourth argument +(useCapture), a boolean that indicated whether to use the browser's +capturing phase or its bubbling phase. Since MSIE does not support the +capturing phase, we removed this argument from 1.6, lest it give users the +false impression that they can use the capturing phase in all browsers.

    + +

    1.6 also introduced setting the this context to the element being +observed, automatically extending the Event object, and the +Event#findElement method.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/on/index.html b/doc/1.7_rc1/dom/event/on/index.html new file mode 100644 index 000000000..81ada0423 --- /dev/null +++ b/doc/1.7_rc1/dom/event/on/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.on + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.on +

    + + + + +
    +
    +
    +
    +
    +
    Event.on(element, eventName, selector, callback) → Event.Handler
    + + +

    Listens for events on an element's descendants, optionally filtering +to match a given CSS selector.

    + +

    Creates an instance of Event.Handler, calls Event.Handler#start, +then returns that instance. Keep a reference to this returned instance if +you later want to unregister the observer.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/pointer/index.html b/doc/1.7_rc1/dom/event/pointer/index.html new file mode 100644 index 000000000..a6626e85b --- /dev/null +++ b/doc/1.7_rc1/dom/event/pointer/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.pointer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.pointer +

    + + + + +
    +
    +
    +
    +
    +
    Event.pointer(event) → Object
    + + +

    Returns the absolute position of the pointer for a mouse event.

    + +

    Returns an object in the form { x: Number, y: Number}.

    + +

    Note that this position is absolute on the page, not on the +viewport.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/pointerx/index.html b/doc/1.7_rc1/dom/event/pointerx/index.html new file mode 100644 index 000000000..417b2ab6e --- /dev/null +++ b/doc/1.7_rc1/dom/event/pointerx/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.pointerX + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.pointerX +

    + + + + +
    +
    +
    +
    +
    +
    Event.pointerX(event) → Number
    + + +

    Returns the absolute horizontal position of the pointer for a mouse +event.

    + +

    Note that this position is absolute on the <body>, not on the +viewport: scrolling right increases the returned value for events on +the same viewport location.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/pointery/index.html b/doc/1.7_rc1/dom/event/pointery/index.html new file mode 100644 index 000000000..0b9da40c8 --- /dev/null +++ b/doc/1.7_rc1/dom/event/pointery/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.pointerY + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.pointerY +

    + + + + +
    +
    +
    +
    +
    +
    Event.pointerY(event) → Number
    + + +

    Returns the absolute vertical position of the pointer for a mouse +event.

    + +

    Note that this position is absolute on the <body>, not on the +viewport: scrolling down increases the returned value for events on +the same viewport location.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/element/index.html b/doc/1.7_rc1/dom/event/prototype/element/index.html new file mode 100644 index 000000000..9e9110ff4 --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/element/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#element + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Event#element +

    + + + + +
    +
    +
    +
    +
    +
    Event#element() → Element
    +
      +
    • + event + (Event) + – An Event object +
    • +
    + + +

    Returns the DOM element on which the event occurred. This method +is deprecated, use Event.findElement instead.

    + +
    Example
    + +

    Here's a simple bit of code which hides any paragraph when directly clicked.

    + +
    document.observe('click', function(event) {
    +  var element = Event.element(event);
    +  if ('P' == element.tagName)
    +    element.hide();
    +});
    +
    +
    + +
    See also
    + +

    There is a subtle distinction between this function and +Event.findElement.

    + +
    Note for Prototype 1.5.0
    + +

    Note that prior to version 1.5.1, if the browser does not support +native DOM extensions (see the Element section for further details), +the element returned by Event.element might very well +not be extended. If you intend to use methods from Element.Methods +on it, you need to wrap the call in the $ function like so:

    + +
    document.observe('click', function(event) {
    +  var element = $(Event.element(event));
    +  // ...
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/extend/index.html b/doc/1.7_rc1/dom/event/prototype/extend/index.html new file mode 100644 index 000000000..410818594 --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/extend/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#extend +

    + + + + +
    +
    +
    +
    +
    +
    Event#extend() → Event
    + + +

    Extends event with all of the methods contained in Event.Methods.

    + +

    Note that all events inside handlers that were registered using +Event.observe or Element.observe will be extended automatically.

    + +

    You need only call Event.extend manually if you register a handler a +different way (e.g., the onclick attribute). We really can't encourage +that sort of thing, though.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/findelement/index.html b/doc/1.7_rc1/dom/event/prototype/findelement/index.html new file mode 100644 index 000000000..fd9884a17 --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/findelement/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#findElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#findElement +

    + + + + +
    +
    +
    +
    +
    +
    Event#findElement([expression]) → Element
    +
      +
    • + event + (Event) + – An Event object +
    • +
    • + expression + (String) + – An optional CSS selector +
    • +
    + + +

    Returns the first DOM element that matches a given CSS selector — +starting with the element on which the event occurred, then moving up +its ancestor chain. If expression is not given, the element which fired +the event is returned.

    + +

    *If no matching element is found, the document itself (HTMLDocument node) +is returned.*

    + +
    Example
    + +

    Here's a simple code that lets you click everywhere on the page and hides +the closest-fitting paragraph around your click (if any).

    + +
    document.observe('click', function(event) {
    +  var element = Event.findElement(event, 'p');
    +  if (element != document)
    +    $(element).hide();
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/isleftclick/index.html b/doc/1.7_rc1/dom/event/prototype/isleftclick/index.html new file mode 100644 index 000000000..9c6abd07c --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/isleftclick/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#isLeftClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#isLeftClick +

    + + + + +
    +
    +
    +
    +
    +
    Event#isLeftClick() → Boolean
    + + +

    Determines whether a button-related mouse event involved the left +mouse button.

    + +

    Keep in mind that the "left" mouse button is actually the "primary" mouse +button. When a mouse is in left-handed mode, the browser will report +clicks of the right button as "left-clicks."

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/ismiddleclick/index.html b/doc/1.7_rc1/dom/event/prototype/ismiddleclick/index.html new file mode 100644 index 000000000..c55de5769 --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/ismiddleclick/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#isMiddleClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#isMiddleClick +

    + + + + +
    +
    +
    +
    +
    +
    Event#isMiddleClick() → Boolean
    + + +

    Determines whether a button-related mouse event involved the middle +mouse button.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/isrightclick/index.html b/doc/1.7_rc1/dom/event/prototype/isrightclick/index.html new file mode 100644 index 000000000..54815ef34 --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/isrightclick/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#isRightClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#isRightClick +

    + + + + +
    +
    +
    +
    +
    +
    Event#isRightClick() → Boolean
    + + +

    Determines whether a button-related mouse event involved the right +mouse button.

    + +

    Keep in mind that the "left" mouse button is actually the "secondary" +mouse button. When a mouse is in left-handed mode, the browser will +report clicks of the left button as "left-clicks."

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/pointer/index.html b/doc/1.7_rc1/dom/event/prototype/pointer/index.html new file mode 100644 index 000000000..6fc653128 --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/pointer/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#pointer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#pointer +

    + + + + +
    +
    +
    +
    +
    +
    Event#pointer() → Object
    + + +

    Returns the absolute position of the pointer for a mouse event.

    + +

    Returns an object in the form { x: Number, y: Number}.

    + +

    Note that this position is absolute on the page, not on the +viewport.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/pointerx/index.html b/doc/1.7_rc1/dom/event/prototype/pointerx/index.html new file mode 100644 index 000000000..9ce07d7aa --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/pointerx/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#pointerX + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#pointerX +

    + + + + +
    +
    +
    +
    +
    +
    Event#pointerX() → Number
    + + +

    Returns the absolute horizontal position of the pointer for a mouse +event.

    + +

    Note that this position is absolute on the <body>, not on the +viewport: scrolling right increases the returned value for events on +the same viewport location.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/pointery/index.html b/doc/1.7_rc1/dom/event/prototype/pointery/index.html new file mode 100644 index 000000000..bd4b3cfa7 --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/pointery/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#pointerY + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#pointerY +

    + + + + +
    +
    +
    +
    +
    +
    Event#pointerY() → Number
    + + +

    Returns the absolute vertical position of the pointer for a mouse +event.

    + +

    Note that this position is absolute on the <body>, not on the +viewport: scrolling down increases the returned value for events on +the same viewport location.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/prototype/stop/index.html b/doc/1.7_rc1/dom/event/prototype/stop/index.html new file mode 100644 index 000000000..8a3daa558 --- /dev/null +++ b/doc/1.7_rc1/dom/event/prototype/stop/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#stop +

    + + + + +
    +
    +
    +
    +
    +
    Event#stop() → undefined
    + + +

    Stops the event's propagation and prevents its eventual default action +from being triggered.

    + +

    Stopping an event also sets a stopped property on that event for +future inspection.

    + +

    There are two aspects to how your browser handles an event once it fires up:

    + +
      +
    1. The browser usually triggers event handlers on the actual element the +event occurred on, then on its parent element, and so on and so forth, +until the document's root element is reached. This is called +event bubbling, and is the most common form of event propagation. You +may very well want to stop this propagation when you just handled an event, +and don't want it to keep bubbling up (or see no need for it).

    2. +
    3. Once your code had a chance to process the event, the browser handles +it as well, if that event has a default behavior. For instance, clicking +on links navigates to them; submitting forms sends them over to the server +side; hitting the Return key in a single-line form field submits it; etc. +You may very well want to prevent this default behavior if you do your own +handling.

    4. +
    + +

    Because stopping one of those aspects means, in 99.9% of the cases, +preventing the other one as well, Prototype bundles both in this stop +function. Calling it on an event object, stops propagation and prevents +the default behavior.

    + +
    Example
    + +

    Here's a simple script that prevents a form from being sent to the server +side if certain field is empty.

    + +
    Event.observe('signinForm', 'submit', function(event) {
    +  var login = $F('login').strip();
    +  if ('' == login) {
    +    Event.stop(event);
    +    // Display the issue one way or another
    +  }
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/stop/index.html b/doc/1.7_rc1/dom/event/stop/index.html new file mode 100644 index 000000000..dc6a73608 --- /dev/null +++ b/doc/1.7_rc1/dom/event/stop/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.stop +

    + + + + +
    +
    +
    +
    +
    +
    Event.stop(event) → undefined
    + + +

    Stops the event's propagation and prevents its eventual default action +from being triggered.

    + +

    Stopping an event also sets a stopped property on that event for +future inspection.

    + +

    There are two aspects to how your browser handles an event once it fires up:

    + +
      +
    1. The browser usually triggers event handlers on the actual element the +event occurred on, then on its parent element, and so on and so forth, +until the document's root element is reached. This is called +event bubbling, and is the most common form of event propagation. You +may very well want to stop this propagation when you just handled an event, +and don't want it to keep bubbling up (or see no need for it).

    2. +
    3. Once your code had a chance to process the event, the browser handles +it as well, if that event has a default behavior. For instance, clicking +on links navigates to them; submitting forms sends them over to the server +side; hitting the Return key in a single-line form field submits it; etc. +You may very well want to prevent this default behavior if you do your own +handling.

    4. +
    + +

    Because stopping one of those aspects means, in 99.9% of the cases, +preventing the other one as well, Prototype bundles both in this stop +function. Calling it on an event object, stops propagation and prevents +the default behavior.

    + +
    Example
    + +

    Here's a simple script that prevents a form from being sent to the server +side if certain field is empty.

    + +
    Event.observe('signinForm', 'submit', function(event) {
    +  var login = $F('login').strip();
    +  if ('' == login) {
    +    Event.stop(event);
    +    // Display the issue one way or another
    +  }
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/event/stopobserving/index.html b/doc/1.7_rc1/dom/event/stopobserving/index.html new file mode 100644 index 000000000..fa27559c2 --- /dev/null +++ b/doc/1.7_rc1/dom/event/stopobserving/index.html @@ -0,0 +1,247 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.stopObserving + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.stopObserving +

    + + + + +
    +
    +
    +
    +
    +
    Event.stopObserving(element[, eventName[, handler]]) → Element
    +
      +
    • + element + (Element | String) + – The element to stop observing, or its ID. +
    • +
    • + eventName + (String) + – (Optional) The name of the event to stop observing, in all lower case, without the "on" — e.g., "click" (not "onclick"). +
    • +
    • + handler + (Function) + – (Optional) The handler to remove; must be the exact same reference that was passed to Event.observe. +
    • +
    + + +

    Unregisters one or more event handlers.

    + +

    If handler is omitted, unregisters all event handlers on element +for that eventName. If eventName is also omitted, unregisters all +event handlers on element. (In each case, only affects handlers +registered via Prototype.)

    + +
    Examples
    + +

    Assuming:

    + +
    $('foo').observe('click', myHandler);
    +
    +
    + +

    ...we can stop observing using that handler like so:

    + +
    $('foo').stopObserving('click', myHandler);
    +
    +
    + +

    If we want to remove all 'click' handlers from 'foo', we leave off the +handler argument:

    + +
    $('foo').stopObserving('click');
    +
    +
    + +

    If we want to remove all handlers for all events from 'foo' (perhaps +we're about to remove it from the DOM), we simply omit both the handler +and the event name:

    + +
    $('foo').stopObserving();
    +
    +
    + +
    A Common Error
    + +

    When using instance methods as observers, it's common to use +Function#bind on them, e.g.:

    + +
    $('foo').observe('click', this.handlerMethod.bind(this));
    +
    +
    + +

    If you do that, this will not work to unregister the handler:

    + +
    $('foo').stopObserving('click', this.handlerMethod.bind(this)); // <== WRONG
    +
    +
    + +

    Function#bind returns a new function every time it's called, and so +if you don't retain the reference you used when observing, you can't +unhook that function specifically. (You can still unhook all handlers +for an event, or all handlers on the element entirely.)

    + +

    To do this, you need to keep a reference to the bound function:

    + +
    this.boundHandlerMethod = this.handlerMethod.bind(this);
    +$('foo').observe('click', this.boundHandlerMethod);
    +
    +
    + +

    ...and then to remove:

    + +
    $('foo').stopObserving('click', this.boundHandlerMethod); // <== Right
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/disable/index.html b/doc/1.7_rc1/dom/form/disable/index.html new file mode 100644 index 000000000..a2a794f9f --- /dev/null +++ b/doc/1.7_rc1/dom/form/disable/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.disable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.disable +

    + + + + +
    +
    +
    +
    +
    +
    Form.disable(form) → Element
    + + +

    Disables the form as a whole. Form controls will be visible but +uneditable.

    + +

    Disabling the form is done by iterating over form elements and calling +Form.Element.disable on them.

    + +
    Note
    + +

    Keep in mind that disabled elements are skipped by serialization +methods! You cannot serialize a disabled form.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/activate/index.html b/doc/1.7_rc1/dom/form/element/activate/index.html new file mode 100644 index 000000000..9b505411f --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/activate/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.activate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.activate +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.activate(element) → Element
    + + +

    Gives focus to a form control and selects its contents if it is a text +input.

    + +

    This method is just a shortcut for focusing and selecting; therefore, +these are equivalent (aside from the fact that the former one will not +return the field) :

    + +
    Form.Element.focus('myelement').select()
    +$('myelement').activate()
    +
    +
    + +

    Guess which call is the nicest? ;)

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/clear/index.html b/doc/1.7_rc1/dom/form/element/clear/index.html new file mode 100644 index 000000000..15dcd68a3 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/clear/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.clear + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.clear +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.clear(element) → Element
    + + +

    Clears the contents of a text input. Returns the element.

    + +
    Example
    + +

    This code sets up a text field in a way that it clears its contents the +first time it receives focus:

    + +
      $('some_field').onfocus = function() {
    +    // if already cleared, do nothing
    +    if (this._cleared) return
    +     // when this code is executed, "this" keyword will in fact be the field itself
    +    this.clear()
    +    this._cleared = true
    +  }
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/disable/index.html b/doc/1.7_rc1/dom/form/element/disable/index.html new file mode 100644 index 000000000..7fe2713c0 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/disable/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.disable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.disable +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.disable(element) → Element
    + + +

    Disables a form control, effectively preventing its value from changing +until it is enabled again.

    + +

    This method sets the native disabled property of an element to true. +You can use this property to check the state of a control.

    + +
    Notes
    + +

    Disabled form controls are never serialized.

    + +

    Never disable a form control as a security measure without having +validation for it server-side. A user with minimal experience of +JavaScript can enable these fields on your site easily using any browser. +Instead, use disabling as a usability enhancement - with it you can +indicate that a specific value should not be changed at the time being.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/enable/index.html b/doc/1.7_rc1/dom/form/element/enable/index.html new file mode 100644 index 000000000..2c7c84977 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/enable/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.enable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.enable +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.enable(element) → Element
    + + +

    Enables a previously disabled form control.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/eventobserver/index.html b/doc/1.7_rc1/dom/form/element/eventobserver/index.html new file mode 100644 index 000000000..a9aa2693a --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/eventobserver/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.EventObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Form.Element.EventObserver +

    + + + + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/focus/index.html b/doc/1.7_rc1/dom/form/element/focus/index.html new file mode 100644 index 000000000..3a8a37fa4 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/focus/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.focus + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.focus +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.focus(element) → Element
    + + +

    Gives keyboard focus to an element. Returns the element.

    + +
    Example
    + +
    Form.Element.focus('searchbox')
    + // Almost equivalent, but does NOT return the form element (uses the native focus() method):
    +$('searchbox').focus()
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/getvalue/index.html b/doc/1.7_rc1/dom/form/element/getvalue/index.html new file mode 100644 index 000000000..9488344c0 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/getvalue/index.html @@ -0,0 +1,192 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.getValue + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.getValue +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.getValue(element) → String | Array
    + + +

    Returns the current value of a form control.

    + +

    A string is returned for most controls; only multiple select boxes +return an array of values.

    + +

    The global shortcut for this method is $F.

    + +
    How to reference form controls by their name
    + +

    This method is consistent with other DOM extensions in that it requires an +element *ID* as the string argument, not the name of the +form control (as some might think). If you want to reference controls by +their names, first find the control the regular JavaScript way and use the +node itself instead of an ID as the argument.

    + +

    For example, if you have an input named "company" in a form with an +ID "contact":

    + +
    var form = $('contact');
    +var input = form['company'];
    + Form.Element.getValue(input);
    + // but, the preferred call is:
    +$(input).getValue(); // we used the $() method so the node gets extended
    + // you can also use the shortcut
    +$F(input);
    +
    +
    + +
    Note
    + +

    An error is thrown ("element has no properties") if the element argument +is an unknown ID.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/index.html b/doc/1.7_rc1/dom/form/element/index.html new file mode 100644 index 000000000..60e8a9510 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/index.html @@ -0,0 +1,275 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Form.Element +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Utilities for dealing with form controls in the DOM.

    + +

    This is a collection of methods that assist in dealing with form controls. +They provide ways to focus, serialize, disable/enable +or extract current value from a specific control.

    + +

    Note that nearly all these methods are available directly on input, +select, and textarea elements. Therefore, these are equivalent:

    + +
    Form.Element.activate('myfield');
    +$('myfield').activate();
    +
    +
    + +

    Naturally, you should always prefer the shortest form suitable in a +situation. Most of these methods also return the element itself (as +indicated by the return type) for chainability.

    +
    +
    + + + +
    +
    +

    Classes

    +
    +
    + + +
    +
    + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/observer/index.html b/doc/1.7_rc1/dom/form/element/observer/index.html new file mode 100644 index 000000000..9f81b139b --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/observer/index.html @@ -0,0 +1,178 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.Observer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Form.Element.Observer +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    An Abstract.TimedObserver subclass that watches for changes to a form +field's value. This triggers the callback when the form field's value +(according to Form.Element.getValue) changes. (Note that when the value +actually changes can vary from browser to browser, particularly with +select boxes.)

    + +

    Form.Element observer implements the getValue() method using +Form.Element.getValue on the given element. See Abstract.TimedObserver +for general documentation on timed observers.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/observer/new/index.html b/doc/1.7_rc1/dom/form/element/observer/new/index.html new file mode 100644 index 000000000..18bad53a5 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/observer/new/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.7_rc1 API documentation | new Form.Element.Observer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Form.Element.Observer +

    + + + + +
    +
    +
    +
    +
    +
    new(element, frequency, callback)
    +
      +
    • + element + (String | Element) + – The form element to watch. Can be an element instance or an ID. +
    • +
    • + frequency + (Number) + – The frequency, in seconds — e.g., 0.33 to check for changes every third of a second. +
    • +
    • + callback + (Function) + – The callback to trigger when the value changes. +
    • +
    + + +

    Creates a Form.Element.Observer.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/present/index.html b/doc/1.7_rc1/dom/form/element/present/index.html new file mode 100644 index 000000000..2a7e77cfc --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/present/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.present + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.present +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.present(element) → Element
    + + +

    Returns true if a text input has contents, false otherwise.

    + +
    Example
    + +

    This method is very handy in a generic form validation routine. +On the following form's submit event, the presence of each text input is +checked and lets the user know if they left a text input blank.

    + +
    <form id="example" class="example" action="#">
    +  <fieldset>
    +    <legend>User Details</legend>
    +    <p id="msg" class="message">Please fill out the following fields:</p>
    +    <p>
    +      <label for="username">Username</label>
    +      <input id="username" type="text" name="username" />
    +    </p>
    +    <p>
    +      <label for="email">Email Address</label>
    +      <input id="email" type="text" name="email" />
    +    </p>
    +    <input type="submit" value="submit" />
    +  </fieldset>
    +</form>
    + <script type="text/javascript">
    +  $('example').onsubmit = function(){
    +    var valid, msg = $('msg')
    +     // are both fields present?
    +    valid = $(this.username).present() && $(this.email).present()
    +     if (valid) {
    +      // in the real world we would return true here to allow the form to be submitted
    +      // return true
    +      msg.update('Passed validation!').style.color = 'green'
    +    } else {
    +      msg.update('Please fill out <em>all</em> the fields.').style.color = 'red'
    +    }
    +    return false
    +  }
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/prototype/activate/index.html b/doc/1.7_rc1/dom/form/element/prototype/activate/index.html new file mode 100644 index 000000000..490d77604 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/prototype/activate/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#activate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#activate +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#activate() → Element
    + + +

    Gives focus to a form control and selects its contents if it is a text +input.

    + +

    This method is just a shortcut for focusing and selecting; therefore, +these are equivalent (aside from the fact that the former one will not +return the field) :

    + +
    Form.Element.focus('myelement').select()
    +$('myelement').activate()
    +
    +
    + +

    Guess which call is the nicest? ;)

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/prototype/clear/index.html b/doc/1.7_rc1/dom/form/element/prototype/clear/index.html new file mode 100644 index 000000000..a20a3e255 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/prototype/clear/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#clear + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#clear +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#clear() → Element
    + + +

    Clears the contents of a text input. Returns the element.

    + +
    Example
    + +

    This code sets up a text field in a way that it clears its contents the +first time it receives focus:

    + +
      $('some_field').onfocus = function() {
    +    // if already cleared, do nothing
    +    if (this._cleared) return
    +     // when this code is executed, "this" keyword will in fact be the field itself
    +    this.clear()
    +    this._cleared = true
    +  }
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/prototype/disable/index.html b/doc/1.7_rc1/dom/form/element/prototype/disable/index.html new file mode 100644 index 000000000..fad732f1b --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/prototype/disable/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#disable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#disable +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#disable() → Element
    + + +

    Disables a form control, effectively preventing its value from changing +until it is enabled again.

    + +

    This method sets the native disabled property of an element to true. +You can use this property to check the state of a control.

    + +
    Notes
    + +

    Disabled form controls are never serialized.

    + +

    Never disable a form control as a security measure without having +validation for it server-side. A user with minimal experience of +JavaScript can enable these fields on your site easily using any browser. +Instead, use disabling as a usability enhancement - with it you can +indicate that a specific value should not be changed at the time being.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/prototype/enable/index.html b/doc/1.7_rc1/dom/form/element/prototype/enable/index.html new file mode 100644 index 000000000..43230b981 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/prototype/enable/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#enable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#enable +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#enable() → Element
    + + +

    Enables a previously disabled form control.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/prototype/getvalue/index.html b/doc/1.7_rc1/dom/form/element/prototype/getvalue/index.html new file mode 100644 index 000000000..4110d4b39 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/prototype/getvalue/index.html @@ -0,0 +1,192 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#getValue + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#getValue +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#getValue() → String | Array
    + + +

    Returns the current value of a form control.

    + +

    A string is returned for most controls; only multiple select boxes +return an array of values.

    + +

    The global shortcut for this method is $F.

    + +
    How to reference form controls by their name
    + +

    This method is consistent with other DOM extensions in that it requires an +element *ID* as the string argument, not the name of the +form control (as some might think). If you want to reference controls by +their names, first find the control the regular JavaScript way and use the +node itself instead of an ID as the argument.

    + +

    For example, if you have an input named "company" in a form with an +ID "contact":

    + +
    var form = $('contact');
    +var input = form['company'];
    + Form.Element.getValue(input);
    + // but, the preferred call is:
    +$(input).getValue(); // we used the $() method so the node gets extended
    + // you can also use the shortcut
    +$F(input);
    +
    +
    + +
    Note
    + +

    An error is thrown ("element has no properties") if the element argument +is an unknown ID.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/prototype/present/index.html b/doc/1.7_rc1/dom/form/element/prototype/present/index.html new file mode 100644 index 000000000..8abc8a709 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/prototype/present/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#present + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#present +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#present() → Element
    + + +

    Returns true if a text input has contents, false otherwise.

    + +
    Example
    + +

    This method is very handy in a generic form validation routine. +On the following form's submit event, the presence of each text input is +checked and lets the user know if they left a text input blank.

    + +
    <form id="example" class="example" action="#">
    +  <fieldset>
    +    <legend>User Details</legend>
    +    <p id="msg" class="message">Please fill out the following fields:</p>
    +    <p>
    +      <label for="username">Username</label>
    +      <input id="username" type="text" name="username" />
    +    </p>
    +    <p>
    +      <label for="email">Email Address</label>
    +      <input id="email" type="text" name="email" />
    +    </p>
    +    <input type="submit" value="submit" />
    +  </fieldset>
    +</form>
    + <script type="text/javascript">
    +  $('example').onsubmit = function(){
    +    var valid, msg = $('msg')
    +     // are both fields present?
    +    valid = $(this.username).present() && $(this.email).present()
    +     if (valid) {
    +      // in the real world we would return true here to allow the form to be submitted
    +      // return true
    +      msg.update('Passed validation!').style.color = 'green'
    +    } else {
    +      msg.update('Please fill out <em>all</em> the fields.').style.color = 'red'
    +    }
    +    return false
    +  }
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/prototype/serialize/index.html b/doc/1.7_rc1/dom/form/element/prototype/serialize/index.html new file mode 100644 index 000000000..d1dbe9fbf --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/prototype/serialize/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#serialize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#serialize +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#serialize() → String
    + + +

    Returns a URL-encoded string representation of a form control in the +name=value format.

    + +

    The result of this method is a string suitable for Ajax requests. However, +it serializes only a single element - if you need to serialize the whole +form use Form.serialize instead.

    + +
    Notes
    + +

    Serializing a disabled control or a one without a name will always result +in an empty string.

    + +

    If you simply need an element's value for reasons other than Ajax +requests, use Form.Element.getValue instead.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/prototype/setvalue/index.html b/doc/1.7_rc1/dom/form/element/prototype/setvalue/index.html new file mode 100644 index 000000000..14dd2939d --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/prototype/setvalue/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#setValue + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#setValue +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#setValue(value) → Element
    + + +

    Sets value to be the value of the form control. Returns the element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/select/index.html b/doc/1.7_rc1/dom/form/element/select/index.html new file mode 100644 index 000000000..64120e433 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/select/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.select +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.select(element) → Element
    + + +

    Selects the current text in a text input. Returns the element.

    + +
    Example
    + +

    Some search boxes are set up so that they auto-select their content when they receive focus.

    + +
      $('searchbox').onfocus = function() {
    +    Form.Element.select(this)
    +     // You can also rely on the native method, but this will NOT return the element!
    +    this.select()
    +  }
    +
    +
    + +
    Focusing + selecting: use Form.Element.activate!
    + +

    The Form.Element.activate method is a nifty way to both focus a form +field and select its current text, all in one portable JavaScript call.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/serialize/index.html b/doc/1.7_rc1/dom/form/element/serialize/index.html new file mode 100644 index 000000000..1c521facc --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/serialize/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.serialize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.serialize +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.serialize(element) → String
    + + +

    Returns a URL-encoded string representation of a form control in the +name=value format.

    + +

    The result of this method is a string suitable for Ajax requests. However, +it serializes only a single element - if you need to serialize the whole +form use Form.serialize instead.

    + +
    Notes
    + +

    Serializing a disabled control or a one without a name will always result +in an empty string.

    + +

    If you simply need an element's value for reasons other than Ajax +requests, use Form.Element.getValue instead.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/element/setvalue/index.html b/doc/1.7_rc1/dom/form/element/setvalue/index.html new file mode 100644 index 000000000..7ff6a15c5 --- /dev/null +++ b/doc/1.7_rc1/dom/form/element/setvalue/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.setValue + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.setValue +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.setValue(element, value) → Element
    + + +

    Sets value to be the value of the form control. Returns the element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/enable/index.html b/doc/1.7_rc1/dom/form/enable/index.html new file mode 100644 index 000000000..c7afaf6b0 --- /dev/null +++ b/doc/1.7_rc1/dom/form/enable/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.enable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.enable +

    + + + + +
    +
    +
    +
    +
    +
    Form.enable(form) → Element
    + + +

    Enables a fully- or partially-disabled form.

    + +

    Enabling the form is done by iterating over form elements and calling +Form.Element.enable on them.

    + +
    Note
    + +

    This will enable all form controls regardless of how they were disabled +(by scripting or by HTML attributes).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/eventobserver/index.html b/doc/1.7_rc1/dom/form/eventobserver/index.html new file mode 100644 index 000000000..c414f9683 --- /dev/null +++ b/doc/1.7_rc1/dom/form/eventobserver/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.EventObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Form.EventObserver +

    + + + + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/findfirstelement/index.html b/doc/1.7_rc1/dom/form/findfirstelement/index.html new file mode 100644 index 000000000..0b230ea35 --- /dev/null +++ b/doc/1.7_rc1/dom/form/findfirstelement/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.findFirstElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.findFirstElement +

    + + + + +
    +
    +
    +
    +
    +
    Form.findFirstElement(form) → Element
    + + +

    Finds the first non-hidden, non-disabled control within the form.

    + +

    The returned object is either an INPUT, SELECT or TEXTAREA element. This +method is used by the Form.focusFirstElement method.

    + +
    Note
    + +

    The result of this method is the element that comes first in the +document order, not the +tabindex order.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/focusfirstelement/index.html b/doc/1.7_rc1/dom/form/focusfirstelement/index.html new file mode 100644 index 000000000..c4ecbde74 --- /dev/null +++ b/doc/1.7_rc1/dom/form/focusfirstelement/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.focusFirstElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.focusFirstElement +

    + + + + +
    +
    +
    +
    +
    +
    Form.focusFirstElement(form) → Element
    + + +

    Gives keyboard focus to the first element of the form. Returns the form.

    + +

    Uses Form.findFirstElement to get the first element and calls +Form.Element.activate on it. This is useful for enhancing usability on +your site by bringing focus on page load to forms such as search forms or +contact forms where a user is ready to start typing right away.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/getelements/index.html b/doc/1.7_rc1/dom/form/getelements/index.html new file mode 100644 index 000000000..6427fc892 --- /dev/null +++ b/doc/1.7_rc1/dom/form/getelements/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.getElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.getElements +

    + + + + +
    +
    +
    +
    +
    +
    Form.getElements(form) → [Element…]
    + + +

    Returns a collection of all controls within a form.

    + +
    Note
    + +

    OPTION elements are not included in the result; only their parent +SELECT control is.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/getinputs/index.html b/doc/1.7_rc1/dom/form/getinputs/index.html new file mode 100644 index 000000000..424b9d6e4 --- /dev/null +++ b/doc/1.7_rc1/dom/form/getinputs/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.getInputs + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.getInputs +

    + + + + +
    +
    +
    +
    +
    +
    Form.getInputs(form [, type [, name]]) → [Element…]
    +
      +
    • + type + (String) + – A value for the type attribute against which to filter. +
    • +
    • + name + (String) + – A value for the name attribute against which to filter. +
    • +
    + + +

    Returns a collection of all INPUT elements in a form.

    + +

    Use optional type and name arguments to restrict the search on +these attributes.

    + +
    Example
    + +
    var form = $('myform');
    + form.getInputs();       // -> all INPUT elements
    +form.getInputs('text'); // -> only text inputs
    + var buttons = form.getInputs('radio', 'education');
    +// -> only radio buttons of name "education"
    + // now disable these radio buttons:
    +buttons.invoke('disable');
    +
    +
    + +
    Note
    + +

    Elements are returned in the document order, not the +tabindex order.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/index.html b/doc/1.7_rc1/dom/form/index.html new file mode 100644 index 000000000..0aee03a11 --- /dev/null +++ b/doc/1.7_rc1/dom/form/index.html @@ -0,0 +1,265 @@ + + + + + Prototype v1.7_rc1 API documentation | Form + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Form +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Utilities for dealing with forms in the DOM.

    + +

    Form is a namespace for all things form-related, packed with form +manipulation and serialization goodness. While it holds methods dealing +with forms as a whole, its submodule Form.Element deals with specific +form controls.

    + +

    Many of these methods are also available directly on form elements.

    +
    +
    + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Form.Element

      + +

      Utilities for dealing with form controls in the DOM.

      +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Form.EventObserver

      + +
    • +
    • +

      Form.Observer

      + +

      An Abstract.TimedObserver subclass that watches for changes to a form. +The callback is triggered when the form changes — e.g., when any +of its fields' values changes, when fields are added/removed, etc.; anything +that affects the serialized form of the form (see Form#serialize).

      +
    • +
    +
    +
    + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/observer/index.html b/doc/1.7_rc1/dom/form/observer/index.html new file mode 100644 index 000000000..e0fe2a3f4 --- /dev/null +++ b/doc/1.7_rc1/dom/form/observer/index.html @@ -0,0 +1,213 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Observer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Form.Observer +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    An Abstract.TimedObserver subclass that watches for changes to a form. +The callback is triggered when the form changes — e.g., when any +of its fields' values changes, when fields are added/removed, etc.; anything +that affects the serialized form of the form (see Form#serialize).

    + +
    Example
    + +

    In this example an observer is used to change the appearance of the form +if any of the values had been changed. It returns to its initial state when +the data is submitted (saved).

    + +
    <form id="example" action="#">
    +  <fieldset>
    +    <legend>Login Preferences</legend>
    +    <p id="msg" class="message">Current settings:</p>
    +    <p>
    +      <label for="greeting">Greeting message</label>
    +      <input id="greeting" type="text" name="greeting" value="Hello world!" />
    +    </p>
    +    <h4>Login options</h4>
    +    <p>
    +        <input id="login-visible" type="checkbox" name="login-visible" checked="checked" />
    +        <label for="login-visible">allow others to see my last login date</label>
    +    </p>
    +    <p>
    +        <input id="land-recent" type="checkbox" name="land-recent" />
    +        <label for="land-recent">land on recent changes overview instead of the Dashboard</label>
    +    </p>
    +    <input type="submit" value="save" />
    +  </fieldset>
    +</form>
    + <script type="text/javascript">
    +  new Form.Observer('example', 0.3, function(form, value){
    +    $('msg').update('Your preferences have changed. Resubmit to save').style.color = 'red'
    +    form.down().setStyle({ background:'lemonchiffon', borderColor:'red' })
    +  })
    +   $('example').onsubmit = function() {
    +    $('msg').update('Preferences saved!').style.color = 'green'
    +    this.down().setStyle({ background:null, borderColor:null })
    +    return false
    +  }
    +</script>
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/observer/new/index.html b/doc/1.7_rc1/dom/form/observer/new/index.html new file mode 100644 index 000000000..8c02bc0a7 --- /dev/null +++ b/doc/1.7_rc1/dom/form/observer/new/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.7_rc1 API documentation | new Form.Observer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Form.Observer +

    + + + + +
    +
    +
    +
    +
    +
    new(element, frequency, callback)
    +
      +
    • + element + (String | Element) + – The element of the form to watch. Can be an element instance or an ID. +
    • +
    • + frequency + (Number) + – The frequency, in seconds -- e.g., 0.33 to check for changes every third of a second. +
    • +
    • + callback + (Function) + – The callback to trigger when the form changes. +
    • +
    + + +

    Creates a Form.Observer.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/disable/index.html b/doc/1.7_rc1/dom/form/prototype/disable/index.html new file mode 100644 index 000000000..4cddb0b2e --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/disable/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#disable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#disable +

    + + + + +
    +
    +
    +
    +
    +
    Form#disable() → Element
    + + +

    Disables the form as a whole. Form controls will be visible but +uneditable.

    + +

    Disabling the form is done by iterating over form elements and calling +Form.Element.disable on them.

    + +
    Note
    + +

    Keep in mind that disabled elements are skipped by serialization +methods! You cannot serialize a disabled form.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/enable/index.html b/doc/1.7_rc1/dom/form/prototype/enable/index.html new file mode 100644 index 000000000..bc16b034a --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/enable/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#enable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#enable +

    + + + + +
    +
    +
    +
    +
    +
    Form#enable() → Element
    + + +

    Enables a fully- or partially-disabled form.

    + +

    Enabling the form is done by iterating over form elements and calling +Form.Element.enable on them.

    + +
    Note
    + +

    This will enable all form controls regardless of how they were disabled +(by scripting or by HTML attributes).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/findfirstelement/index.html b/doc/1.7_rc1/dom/form/prototype/findfirstelement/index.html new file mode 100644 index 000000000..34fdc1477 --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/findfirstelement/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#findFirstElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#findFirstElement +

    + + + + +
    +
    +
    +
    +
    +
    Form#findFirstElement() → Element
    + + +

    Finds the first non-hidden, non-disabled control within the form.

    + +

    The returned object is either an INPUT, SELECT or TEXTAREA element. This +method is used by the Form.focusFirstElement method.

    + +
    Note
    + +

    The result of this method is the element that comes first in the +document order, not the +tabindex order.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/focusfirstelement/index.html b/doc/1.7_rc1/dom/form/prototype/focusfirstelement/index.html new file mode 100644 index 000000000..4eb30ff77 --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/focusfirstelement/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#focusFirstElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#focusFirstElement +

    + + + + +
    +
    +
    +
    +
    +
    Form#focusFirstElement() → Element
    + + +

    Gives keyboard focus to the first element of the form. Returns the form.

    + +

    Uses Form.findFirstElement to get the first element and calls +Form.Element.activate on it. This is useful for enhancing usability on +your site by bringing focus on page load to forms such as search forms or +contact forms where a user is ready to start typing right away.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/getelements/index.html b/doc/1.7_rc1/dom/form/prototype/getelements/index.html new file mode 100644 index 000000000..780ec82cf --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/getelements/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#getElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#getElements +

    + + + + +
    +
    +
    +
    +
    +
    Form#getElements() → [Element…]
    + + +

    Returns a collection of all controls within a form.

    + +
    Note
    + +

    OPTION elements are not included in the result; only their parent +SELECT control is.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/getinputs/index.html b/doc/1.7_rc1/dom/form/prototype/getinputs/index.html new file mode 100644 index 000000000..ee50d66ca --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/getinputs/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#getInputs + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#getInputs +

    + + + + +
    +
    +
    +
    +
    +
    Form#getInputs([type [, name]]) → [Element…]
    +
      +
    • + type + (String) + – A value for the type attribute against which to filter. +
    • +
    • + name + (String) + – A value for the name attribute against which to filter. +
    • +
    + + +

    Returns a collection of all INPUT elements in a form.

    + +

    Use optional type and name arguments to restrict the search on +these attributes.

    + +
    Example
    + +
    var form = $('myform');
    + form.getInputs();       // -> all INPUT elements
    +form.getInputs('text'); // -> only text inputs
    + var buttons = form.getInputs('radio', 'education');
    +// -> only radio buttons of name "education"
    + // now disable these radio buttons:
    +buttons.invoke('disable');
    +
    +
    + +
    Note
    + +

    Elements are returned in the document order, not the +tabindex order.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/request/index.html b/doc/1.7_rc1/dom/form/prototype/request/index.html new file mode 100644 index 000000000..3c6eee84f --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/request/index.html @@ -0,0 +1,239 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#request +

    + + + + +
    +
    +
    +
    +
    +
    Form#request([options]) → Ajax.Request
    + + + +

    A convenience method for serializing and submitting the form via an +Ajax.Request to the URL of the form's action attribute.

    + +

    The options parameter is passed to the Ajax.Request instance, +allowing one to override the HTTP method and/or specify additional +parameters and callbacks.

    + +
      +
    • If the form has a method attribute, its value is used for the +Ajax.Request method option. If a method option is passed to +request(), it takes precedence over the form's method attribute. If +neither is specified, method defaults to "POST".

    • +
    • Key-value pairs specified in the parameters option (either as a hash +or a query string) will be merged with (and take precedence over) the +serialized form parameters.

    • +
    + +
    Example
    + +

    Suppose you have this HTML form:

    + +
    <form id="person-example" method="POST" action="/user/info">
    +  <fieldset><legend>User info</legend>
    +    <ul>
    +      <li>
    +        <label for="username">Username:</label>
    +        <input type="text" name="username" id="username" value="" />
    +      </li>
    +      <li>
    +        <label for="age">Age:</label>
    +        <input type="text" name="age" id="age" value="" size="3" />
    +      </li>
    +      <li>
    +        <label for="hobbies">Your hobbies are:</label>
    +        <select name="hobbies[]" id="hobbies" multiple="multiple">
    +          <option>coding</option>
    +          <option>swimming</option>
    +          <option>biking</option>
    +          <option>hiking</option>
    +          <option>drawing</option>
    +        </select>
    +      </li>
    +    </ul>
    +    <input type="submit" value="serialize!" />
    +  </fieldset>
    +</form>
    +
    +
    + +

    You can easily post it with Ajax like this:

    + +
    $('person-example').request(); //done - it's posted
    + // do the same with a callback:
    +$('person-example').request({
    +  onComplete: function(){ alert('Form data saved!') }
    +})
    +
    +
    + +

    To override the HTTP method and add some parameters, simply use method +and parameters in the options. In this example we set the method to GET +and set two fixed parameters: +interests and hobbies. The latter already exists in the form but this +value will take precedence.

    + +
    $('person-example').request({
    +  method: 'get',
    +  parameters: { interests:'JavaScript', 'hobbies[]':['programming', 'music'] },
    +  onComplete: function(){ alert('Form data saved!') }
    +})
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/reset/index.html b/doc/1.7_rc1/dom/form/prototype/reset/index.html new file mode 100644 index 000000000..68bf212c5 --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/reset/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#reset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#reset +

    + + + + +
    +
    +
    +
    +
    +
    Form#reset() → Element
    + + +

    Resets a form to its default values.

    + +

    Example usage:

    + +
    Form.reset('contact')
    + // equivalent:
    +$('contact').reset()
    + // both have the same effect as pressing the reset button
    +
    +
    + +

    This method allows you to programatically reset a form. It is a wrapper +for the reset() method native to HTMLFormElement.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/prototype/serialize/index.html b/doc/1.7_rc1/dom/form/prototype/serialize/index.html new file mode 100644 index 000000000..044de1ef1 --- /dev/null +++ b/doc/1.7_rc1/dom/form/prototype/serialize/index.html @@ -0,0 +1,194 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#serialize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#serialize +

    + + + + +
    +
    +
    +
    +
    +
    Form#serialize([options]) → String | Object
    +
      +
    • + options + (Object) + – A list of options that affect the return value of the method. +
    • +
    + + +

    Serializes form data to a string suitable for Ajax requests (default +behavior) or, if the hash option evaluates to true, an object hash +where keys are form control names and values are data.

    + +

    Depending of whether or not the hash option evaluates to true, the +result is either an object of the form {name: "johnny", color: "blue"} +or a String of the form "name=johnny&color=blue", suitable for +parameters in an Ajax request. This method mimics the way browsers +serialize forms natively so that form data can be sent without refreshing +the page.

    + +

    See Form.serializeElements for more details on the options.

    + +
    Examples
    + +
    $('person-example').serialize()
    +// -> 'username=sulien&age=22&hobbies=coding&hobbies=hiking'
    + $('person-example').serialize(true)
    +// -> {username: 'sulien', age: '22', hobbies: ['coding', 'hiking']}
    +
    +
    + +
    Notes
    + +

    Disabled form elements are not serialized (as per W3C HTML recommendation). +Also, file inputs are skipped as they cannot be serialized and sent using +only JavaScript.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/request/index.html b/doc/1.7_rc1/dom/form/request/index.html new file mode 100644 index 000000000..a6ead8fb7 --- /dev/null +++ b/doc/1.7_rc1/dom/form/request/index.html @@ -0,0 +1,239 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.request +

    + + + + +
    +
    +
    +
    +
    +
    Form.request(form[, options]) → Ajax.Request
    + + + +

    A convenience method for serializing and submitting the form via an +Ajax.Request to the URL of the form's action attribute.

    + +

    The options parameter is passed to the Ajax.Request instance, +allowing one to override the HTTP method and/or specify additional +parameters and callbacks.

    + +
      +
    • If the form has a method attribute, its value is used for the +Ajax.Request method option. If a method option is passed to +request(), it takes precedence over the form's method attribute. If +neither is specified, method defaults to "POST".

    • +
    • Key-value pairs specified in the parameters option (either as a hash +or a query string) will be merged with (and take precedence over) the +serialized form parameters.

    • +
    + +
    Example
    + +

    Suppose you have this HTML form:

    + +
    <form id="person-example" method="POST" action="/user/info">
    +  <fieldset><legend>User info</legend>
    +    <ul>
    +      <li>
    +        <label for="username">Username:</label>
    +        <input type="text" name="username" id="username" value="" />
    +      </li>
    +      <li>
    +        <label for="age">Age:</label>
    +        <input type="text" name="age" id="age" value="" size="3" />
    +      </li>
    +      <li>
    +        <label for="hobbies">Your hobbies are:</label>
    +        <select name="hobbies[]" id="hobbies" multiple="multiple">
    +          <option>coding</option>
    +          <option>swimming</option>
    +          <option>biking</option>
    +          <option>hiking</option>
    +          <option>drawing</option>
    +        </select>
    +      </li>
    +    </ul>
    +    <input type="submit" value="serialize!" />
    +  </fieldset>
    +</form>
    +
    +
    + +

    You can easily post it with Ajax like this:

    + +
    $('person-example').request(); //done - it's posted
    + // do the same with a callback:
    +$('person-example').request({
    +  onComplete: function(){ alert('Form data saved!') }
    +})
    +
    +
    + +

    To override the HTTP method and add some parameters, simply use method +and parameters in the options. In this example we set the method to GET +and set two fixed parameters: +interests and hobbies. The latter already exists in the form but this +value will take precedence.

    + +
    $('person-example').request({
    +  method: 'get',
    +  parameters: { interests:'JavaScript', 'hobbies[]':['programming', 'music'] },
    +  onComplete: function(){ alert('Form data saved!') }
    +})
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/reset/index.html b/doc/1.7_rc1/dom/form/reset/index.html new file mode 100644 index 000000000..91dc27776 --- /dev/null +++ b/doc/1.7_rc1/dom/form/reset/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.reset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.reset +

    + + + + +
    +
    +
    +
    +
    +
    Form.reset(form) → Element
    + + +

    Resets a form to its default values.

    + +

    Example usage:

    + +
    Form.reset('contact')
    + // equivalent:
    +$('contact').reset()
    + // both have the same effect as pressing the reset button
    +
    +
    + +

    This method allows you to programatically reset a form. It is a wrapper +for the reset() method native to HTMLFormElement.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/serialize/index.html b/doc/1.7_rc1/dom/form/serialize/index.html new file mode 100644 index 000000000..c24049e3a --- /dev/null +++ b/doc/1.7_rc1/dom/form/serialize/index.html @@ -0,0 +1,194 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.serialize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.serialize +

    + + + + +
    +
    +
    +
    +
    +
    Form.serialize(form[, options]) → String | Object
    +
      +
    • + options + (Object) + – A list of options that affect the return value of the method. +
    • +
    + + +

    Serializes form data to a string suitable for Ajax requests (default +behavior) or, if the hash option evaluates to true, an object hash +where keys are form control names and values are data.

    + +

    Depending of whether or not the hash option evaluates to true, the +result is either an object of the form {name: "johnny", color: "blue"} +or a String of the form "name=johnny&color=blue", suitable for +parameters in an Ajax request. This method mimics the way browsers +serialize forms natively so that form data can be sent without refreshing +the page.

    + +

    See Form.serializeElements for more details on the options.

    + +
    Examples
    + +
    $('person-example').serialize()
    +// -> 'username=sulien&age=22&hobbies=coding&hobbies=hiking'
    + $('person-example').serialize(true)
    +// -> {username: 'sulien', age: '22', hobbies: ['coding', 'hiking']}
    +
    +
    + +
    Notes
    + +

    Disabled form elements are not serialized (as per W3C HTML recommendation). +Also, file inputs are skipped as they cannot be serialized and sent using +only JavaScript.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/form/serializeelements/index.html b/doc/1.7_rc1/dom/form/serializeelements/index.html new file mode 100644 index 000000000..6a60f89ab --- /dev/null +++ b/doc/1.7_rc1/dom/form/serializeelements/index.html @@ -0,0 +1,228 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.serializeElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.serializeElements +

    + + + + +
    +
    +
    +
    +
    +
    Form.serializeElements(elements[, options]) → String | Object
    +
      +
    • + elements + (Array) + – A collection of elements to include in the serialization. +
    • +
    • + options + (Object) + – (Optional) A set of options that affect the return value of the method. +
    • +
    + + +

    Serialize an array of form elements to an object or string suitable +for Ajax requests.

    + +

    As per the HTML spec, disabled fields are not included.

    + +

    If multiple elements have the same name and we're returning an object, +the value for that key in the object will be an array of the field values +in the order they appeared on the array of elements.

    + +

    The preferred method to serialize a form is Form.serialize. Refer to +it for further information and examples on the hash option. However, +with Form.serializeElements you can serialize specific input +elements of your choice, allowing you to specify a subset of form elements +that you want to serialize data from.

    + +
    The Options
    + +

    The options allow you to control two things: What kind of return +value you get (an object or a string), and whether and which submit +fields are included in that object or string.

    + +

    If you do not supply an options object at all, the options +{ hash: false } are used.

    + +

    If you supply an options object, it may have the following options:

    + +
      +
    • hash (Boolean): true to return a plain object with keys and +values (not a Hash; see below), false to return a String in query +string format. If you supply an options object with no hash member, +hash defaults to true. Note that this is not the same as leaving +off the options object entirely (see above).
    • +
    • submit (Boolean | String): In essence: If you omit this option +the first submit button in the form is included; if you supply false, +no submit buttons are included; if you supply the name of a submit +button, the first button with that name is included. Note that the +false value must really be false, not falsey; +falsey-but-not-false is like omitting the option.
    • +
    + +

    (Deprecated) If you pass in a Boolean instead of an object for +options, it is used as the hash option and all other options are +defaulted.

    + +
    A hash, not a Hash
    + +

    If you opt to receive an object, it is a plain JavaScript object with keys +and values, not a Hash. All JavaScript objects are hashes in the +lower-case sense of the word, which is why the option has that +somewhat-confusing name.

    + +
    Examples
    + +

    To serialize all input elements of type "text":

    + +
    Form.serializeElements( $('myform').getInputs('text') )
    +// -> serialized data
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/index.html b/doc/1.7_rc1/dom/index.html new file mode 100644 index 000000000..00b1da14d --- /dev/null +++ b/doc/1.7_rc1/dom/index.html @@ -0,0 +1,208 @@ + + + + + Prototype v1.7_rc1 API documentation | DOM section + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +

    + section DOM section +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to DOM elements, plus other utilities for DOM traversal +and modification.

    + +

    Prototype's DOM extensions represent a large portion of where you'll spend +your time. Prototype adds many convenience methods to elements returned by +the $ function. For instance, you can write

    + +
    $('comments').addClassName('active').show();
    +
    +
    + +

    to get the element with the ID of comments, add a class name to it, and +show it (if it was previously hidden).

    + +

    In other words, Prototype adds "instance" methods to DOM nodes. This is +made possible by direct extension of the backing DOM objects (in browsers +that support it) and by manual extension of individual nodes (in browsers +that do not).

    +
    +
    + + + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      document

      + +

      Prototype extends the built-in document object with several convenience +methods related to events.

      +
    • +
    • +

      Form

      + +

      Utilities for dealing with forms in the DOM.

      +
    • +
    • +

      Abstract

      + +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Element

      + +

      The Element object provides a variety of powerful DOM methods for +interacting with DOM elements — creating them, updating them, +traversing them, etc. You can access these either as methods of Element +itself, passing in the element to work with as the first argument, or as +methods on extended element instances:

      +
    • +
    • +

      Event

      + +

      The namespace for Prototype's event system.

      +
    • +
    • +

      Selector

      + +

      A class that queries the document for elements that match a given CSS +selector.

      +
    • +
    +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/selector/findchildelements/index.html b/doc/1.7_rc1/dom/selector/findchildelements/index.html new file mode 100644 index 000000000..6ec837361 --- /dev/null +++ b/doc/1.7_rc1/dom/selector/findchildelements/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector.findChildElements + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Selector.findChildElements +

    + + + + +
    +
    +
    +
    +
    +
    Selector.findChildElements(element, expressions) → [Element…]
    + + +

    Searches beneath element for any elements that match the selector +(or selectors) specified in expressions.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/selector/findelement/index.html b/doc/1.7_rc1/dom/selector/findelement/index.html new file mode 100644 index 000000000..22d1cc43e --- /dev/null +++ b/doc/1.7_rc1/dom/selector/findelement/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector.findElement + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Selector.findElement +

    + + + + +
    +
    +
    +
    +
    +
    Selector.findElement(elements, expression[, index = 0]) → Element
    Selector.findElement(elements[, index = 0]) → Element
    + + +

    Returns the indexth element in the collection that matches +expression.

    + +

    Returns the indexth element overall if expression is not given.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/selector/index.html b/doc/1.7_rc1/dom/selector/index.html new file mode 100644 index 000000000..4913dffb0 --- /dev/null +++ b/doc/1.7_rc1/dom/selector/index.html @@ -0,0 +1,190 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class Selector +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A class that queries the document for elements that match a given CSS +selector.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Selector

    +
    +
    + + + +
    +
    +

    Class methods

    +
    + +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/selector/matchelements/index.html b/doc/1.7_rc1/dom/selector/matchelements/index.html new file mode 100644 index 000000000..dfc4d7823 --- /dev/null +++ b/doc/1.7_rc1/dom/selector/matchelements/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector.matchElements + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Selector.matchElements +

    + + + + +
    +
    +
    +
    +
    +
    Selector.matchElements(elements, expression) → [Element…]
    + + +

    Filters the given collection of elements with expression.

    + +

    The only nodes returned will be those that match the given CSS selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/selector/new/index.html b/doc/1.7_rc1/dom/selector/new/index.html new file mode 100644 index 000000000..1ddb02c0d --- /dev/null +++ b/doc/1.7_rc1/dom/selector/new/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | new Selector + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + constructor new Selector +

    + + + + +
    +
    +
    +
    +
    +
    new(expression)
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Creates a Selector with the given CSS selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/selector/prototype/findelements/index.html b/doc/1.7_rc1/dom/selector/prototype/findelements/index.html new file mode 100644 index 000000000..e9b7f4357 --- /dev/null +++ b/doc/1.7_rc1/dom/selector/prototype/findelements/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector#findElements + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Selector#findElements +

    + + + + +
    +
    +
    +
    +
    +
    Selector#findElements(root) → [Element…]
    +
      +
    • + root + (Element | document) + – A "scope" to search within. All results will be descendants of this node. +
    • +
    + + +

    Searches the document for elements that match the instance's CSS +selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/dom/selector/prototype/match/index.html b/doc/1.7_rc1/dom/selector/prototype/match/index.html new file mode 100644 index 000000000..1714c74e8 --- /dev/null +++ b/doc/1.7_rc1/dom/selector/prototype/match/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector#match + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Selector#match +

    + + + + +
    +
    +
    +
    +
    +
    Selector#match(element) → Boolean
    + + +

    Tests whether a element matches the instance's CSS selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/images/alias.png b/doc/1.7_rc1/images/alias.png new file mode 100755 index 000000000..6332fefea Binary files /dev/null and b/doc/1.7_rc1/images/alias.png differ diff --git a/doc/1.7_rc1/images/class.png b/doc/1.7_rc1/images/class.png new file mode 100644 index 000000000..e1510c169 Binary files /dev/null and b/doc/1.7_rc1/images/class.png differ diff --git a/doc/1.7_rc1/images/class_deprecated.png b/doc/1.7_rc1/images/class_deprecated.png new file mode 100644 index 000000000..9b7467990 Binary files /dev/null and b/doc/1.7_rc1/images/class_deprecated.png differ diff --git a/doc/1.7_rc1/images/class_method.png b/doc/1.7_rc1/images/class_method.png new file mode 100644 index 000000000..362e29562 Binary files /dev/null and b/doc/1.7_rc1/images/class_method.png differ diff --git a/doc/1.7_rc1/images/class_property.png b/doc/1.7_rc1/images/class_property.png new file mode 100755 index 000000000..ebaf0e874 Binary files /dev/null and b/doc/1.7_rc1/images/class_property.png differ diff --git a/doc/1.7_rc1/images/constant.png b/doc/1.7_rc1/images/constant.png new file mode 100644 index 000000000..c4295ec0d Binary files /dev/null and b/doc/1.7_rc1/images/constant.png differ diff --git a/doc/1.7_rc1/images/constructor.png b/doc/1.7_rc1/images/constructor.png new file mode 100755 index 000000000..565a9330e Binary files /dev/null and b/doc/1.7_rc1/images/constructor.png differ diff --git a/doc/1.7_rc1/images/deprecated.png b/doc/1.7_rc1/images/deprecated.png new file mode 100644 index 000000000..3f145ccce Binary files /dev/null and b/doc/1.7_rc1/images/deprecated.png differ diff --git a/doc/1.7_rc1/images/description.png b/doc/1.7_rc1/images/description.png new file mode 100755 index 000000000..5c870176d Binary files /dev/null and b/doc/1.7_rc1/images/description.png differ diff --git a/doc/1.7_rc1/images/grid.png b/doc/1.7_rc1/images/grid.png new file mode 100644 index 000000000..151ac265d Binary files /dev/null and b/doc/1.7_rc1/images/grid.png differ diff --git a/doc/1.7_rc1/images/header-logo-small.png b/doc/1.7_rc1/images/header-logo-small.png new file mode 100644 index 000000000..f377977fb Binary files /dev/null and b/doc/1.7_rc1/images/header-logo-small.png differ diff --git a/doc/1.7_rc1/images/header-logo.png b/doc/1.7_rc1/images/header-logo.png new file mode 100644 index 000000000..4f6c7c186 Binary files /dev/null and b/doc/1.7_rc1/images/header-logo.png differ diff --git a/doc/1.7_rc1/images/header-stripe-small.png b/doc/1.7_rc1/images/header-stripe-small.png new file mode 100644 index 000000000..e10464063 Binary files /dev/null and b/doc/1.7_rc1/images/header-stripe-small.png differ diff --git a/doc/1.7_rc1/images/header-stripe.png b/doc/1.7_rc1/images/header-stripe.png new file mode 100644 index 000000000..2254f7c83 Binary files /dev/null and b/doc/1.7_rc1/images/header-stripe.png differ diff --git a/doc/1.7_rc1/images/information.png b/doc/1.7_rc1/images/information.png new file mode 100755 index 000000000..12cd1aef9 Binary files /dev/null and b/doc/1.7_rc1/images/information.png differ diff --git a/doc/1.7_rc1/images/instance_method.png b/doc/1.7_rc1/images/instance_method.png new file mode 100644 index 000000000..f6464ab43 Binary files /dev/null and b/doc/1.7_rc1/images/instance_method.png differ diff --git a/doc/1.7_rc1/images/instance_property.png b/doc/1.7_rc1/images/instance_property.png new file mode 100755 index 000000000..83ec984bd Binary files /dev/null and b/doc/1.7_rc1/images/instance_property.png differ diff --git a/doc/1.7_rc1/images/logo.png b/doc/1.7_rc1/images/logo.png new file mode 100644 index 000000000..6ff25884e Binary files /dev/null and b/doc/1.7_rc1/images/logo.png differ diff --git a/doc/1.7_rc1/images/menu-flap.png b/doc/1.7_rc1/images/menu-flap.png new file mode 100644 index 000000000..4424406b0 Binary files /dev/null and b/doc/1.7_rc1/images/menu-flap.png differ diff --git a/doc/1.7_rc1/images/method.png b/doc/1.7_rc1/images/method.png new file mode 100644 index 000000000..35efa7594 Binary files /dev/null and b/doc/1.7_rc1/images/method.png differ diff --git a/doc/1.7_rc1/images/method_deprecated.png b/doc/1.7_rc1/images/method_deprecated.png new file mode 100644 index 000000000..ee77e485f Binary files /dev/null and b/doc/1.7_rc1/images/method_deprecated.png differ diff --git a/doc/1.7_rc1/images/mixin.png b/doc/1.7_rc1/images/mixin.png new file mode 100644 index 000000000..11a7f8fed Binary files /dev/null and b/doc/1.7_rc1/images/mixin.png differ diff --git a/doc/1.7_rc1/images/namespace.png b/doc/1.7_rc1/images/namespace.png new file mode 100644 index 000000000..f2f7b73dd Binary files /dev/null and b/doc/1.7_rc1/images/namespace.png differ diff --git a/doc/1.7_rc1/images/property.png b/doc/1.7_rc1/images/property.png new file mode 100755 index 000000000..ebaf0e874 Binary files /dev/null and b/doc/1.7_rc1/images/property.png differ diff --git a/doc/1.7_rc1/images/related_to.png b/doc/1.7_rc1/images/related_to.png new file mode 100755 index 000000000..25eacb7c2 Binary files /dev/null and b/doc/1.7_rc1/images/related_to.png differ diff --git a/doc/1.7_rc1/images/search-background.png b/doc/1.7_rc1/images/search-background.png new file mode 100644 index 000000000..76295000a Binary files /dev/null and b/doc/1.7_rc1/images/search-background.png differ diff --git a/doc/1.7_rc1/images/section-background.png b/doc/1.7_rc1/images/section-background.png new file mode 100644 index 000000000..d3cf11e39 Binary files /dev/null and b/doc/1.7_rc1/images/section-background.png differ diff --git a/doc/1.7_rc1/images/section.png b/doc/1.7_rc1/images/section.png new file mode 100644 index 000000000..d9d598569 Binary files /dev/null and b/doc/1.7_rc1/images/section.png differ diff --git a/doc/1.7_rc1/images/subclass.png b/doc/1.7_rc1/images/subclass.png new file mode 100755 index 000000000..9ebf013a2 Binary files /dev/null and b/doc/1.7_rc1/images/subclass.png differ diff --git a/doc/1.7_rc1/images/superclass.png b/doc/1.7_rc1/images/superclass.png new file mode 100755 index 000000000..9ebf013a2 Binary files /dev/null and b/doc/1.7_rc1/images/superclass.png differ diff --git a/doc/1.7_rc1/images/tagline.png b/doc/1.7_rc1/images/tagline.png new file mode 100644 index 000000000..85b366caa Binary files /dev/null and b/doc/1.7_rc1/images/tagline.png differ diff --git a/doc/1.7_rc1/images/utility.png b/doc/1.7_rc1/images/utility.png new file mode 100755 index 000000000..59af16382 Binary files /dev/null and b/doc/1.7_rc1/images/utility.png differ diff --git a/doc/1.7_rc1/index.html b/doc/1.7_rc1/index.html new file mode 100644 index 000000000..de3139008 --- /dev/null +++ b/doc/1.7_rc1/index.html @@ -0,0 +1,214 @@ + + + + + Prototype v1.7_rc1 API documentation | Home + + + + + + + + + + + + + + + + +
    + + +
    + +
    +

    Prototype

    + +

    An object-oriented JavaScript framework

    + +

    Prototype is a JavaScript framework that aims to ease development of dynamic +web applications. It offers a familiar class-style OO framework, extensive +Ajax support, higher-order programming constructs, and easy DOM manipulation.

    + +

    Targeted platforms

    + +

    Prototype currently targets the following platforms:

    + +
      +
    • Microsoft Internet Explorer for Windows, version 6.0 and higher
    • +
    • Mozilla Firefox 1.5 and higher
    • +
    • Apple Safari 2.0.4 and higher
    • +
    • Opera 9.25 and higher
    • +
    • Chrome 1.0 and higher
    • +
    + +

    Using Prototype

    + +

    To use Prototype in your application, download the latest release from the +Prototype web site (http://prototypejs.org/download) and copy +dist/prototype.js to a suitable location. Then include it in your HTML +like so:

    + +
    <script type="text/javascript" src="/path/to/prototype.js"></script>
    +
    +
    + +

    Building Prototype from source

    + +

    prototype.js is a composite file generated from many source files in +the src/ directory. To build Prototype, you'll need:

    + +
      +
    • a copy of the Prototype source tree, either from a distribution tarball or +from the Git repository (see below)
    • +
    • Ruby 1.8.2 or higher (http://www.ruby-lang.org/)
    • +
    • Rake--Ruby Make (http://rake.rubyforge.org/)
    • +
    • RDoc, if your Ruby distribution does not include it
    • +
    + +

    From the root Prototype directory,

    + +
      +
    • rake dist will preprocess the Prototype source using Sprockets and +generate the composite dist/prototype.js.
    • +
    • rake package will create a distribution tarball in the +pkg/ directory.
    • +
    + +

    Contributing to Prototype

    + +

    Check out the Prototype source with

    + +
    $ git clone git://github.com/sstephenson/prototype.git
    +$ cd prototype
    +$ git submodule init
    +$ git submodule update vendor/sprockets vendor/pdoc vendor/unittest_js
    +
    +
    + +

    Find out how to contribute: http://prototypejs.org/contribute.

    + +

    Documentation

    + +

    Please see the online Prototype API: http://api.prototypejs.org.

    +
    + +
    +
    +

    Sections

    +
    +
    + +
      +
    • +

      + Ajax +

      +

      Prototype's APIs around the XmlHttpRequest object.

      +
    • +
    • +

      + DOM +

      +

      Extensions to DOM elements, plus other utilities for DOM traversal +and modification.

      +
    • +
    • +

      + Language +

      +

      Additions to JavaScript's "standard library" and extensions to +built-in JavaScript objects.

      +
    • +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/javascripts/application.js b/doc/1.7_rc1/javascripts/application.js new file mode 100644 index 000000000..a0303de26 --- /dev/null +++ b/doc/1.7_rc1/javascripts/application.js @@ -0,0 +1,478 @@ +//= require + +if (!Prototype || Prototype.Version.indexOf('1.6') !== 0) { + throw "This script requires Prototype >= 1.6."; +} + +Object.isDate = function(object) { + return object instanceof Date; +}; + +/** + * class Cookie + * Creates a cookie. +**/ +var Cookie = Class.create({ + /** + * new Cookie(name, value[, expires]) + * + * - name (String): The name of the cookie. + * - value (String): The value of the cookie. + * - expires (Number | Date): Exact date (or number of days from now) that + * the cookie will expire. + **/ + initialize: function(name, value, expires) { + expires = expires || ""; + if (Object.isNumber(expires)) { + var days = expires; + expires = new Date(); + expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000)); + } + + if (Object.isDate(expires)) + expires = expires.toGMTString(); + + if (!Object.isUndefined(expires) && expires !== "") + expires = "; expires=" + expires; + + this.name = name; + this.value = value; + this.expires = expires; + + document.cookie = name + "=" + value + expires + "; path=/"; + }, + + toString: function() { + return this.value; + }, + + inspect: function() { + return "#".interpolate(this); + } +}); + +/** + * Cookie +**/ +Object.extend(Cookie, { + /** + * Cookie.set(name, value, expires) + * + * Alias of [[Cookie#initialize]]. + **/ + set: function(name, value, expires) { + return new Cookie(name, value, expires); + }, + + /** + * Cookie.get(name) + * + * Returns the value of the cookie with the given name. + * - name (String): The name of the cookie to retrieve. + **/ + get: function(name) { + var c = document.cookie.split(';'); + + for (var i = 0, cookie; i < c.length; i++) { + cookie = c[i].split('='); + if (cookie[0].strip() === name) + return cookie[1].strip(); + } + + return null; + }, + + /** + * Cookie.unset(name) + * + * Deletes a cookie. + * - name (String): The name of the cookie to delete. + * + **/ + unset: function(name) { + return Cookie.set(name, "", -1); + } +}); + +Cookie.erase = Cookie.unset; + + + +if (typeof PDoc === 'undefined') { + window.PDoc = { + Sidebar: {} + }; +} + +// HISTORY MANAGER (sort of) +// Polls for changes to the hash. + +(function() { + var PREVIOUS_HASH = null; + + function poll() { + var hash = window.location.hash; + if (hash && hash !== PREVIOUS_HASH) { + document.fire('hash:changed', { + previous: PREVIOUS_HASH, current: hash + }); + } + PREVIOUS_HASH = hash; + window.setTimeout(arguments.callee, 100); + } + + Event.observe(window, 'load', poll); +})(); + +Object.extend(PDoc.Sidebar, { + getActiveTab: function() { + var activeTab = $('sidebar_tabs').down('.active'); + if (!activeTab) return null; + + var href = activeTab.readAttribute('href'); + return href.endsWith('menu_pane') ? 'menu_pane' : 'search_pane'; + }, + + // Remember the state of the sidebar so it can be restored on the next page. + serialize: function() { + var state = $H({ + activeTab: PDoc.Sidebar.getActiveTab(), + menuScrollOffset: $('menu_pane').scrollTop, + searchScrollOffset: $('search_results').scrollTop, + searchValue: $('search').getValue() + }); + + return escape(state.toJSON()); + }, + + // Restore the tree to a certain point based on a cookie. + restore: function(state) { + try { + state = unescape(state).evalJSON(); + var filterer = $('search').retrieve('filterer'); + filterer.setSearchValue(state.searchValue); + + (function() { + $('menu_pane').scrollTop = state.menuScrollOffset; + $('search_results').scrollTop = state.searchScrollOffset; + }).defer(); + } catch(error) { + console.log(error); + if (!(error instanceof SyntaxError)) throw error; + } + } +}); + + + +// Live API search. +PDoc.Sidebar.Filterer = Class.create({ + initialize: function(element, options) { + this.element = $(element); + this.options = Object.extend( + Object.clone(PDoc.Sidebar.Filterer.DEFAULT_OPTIONS), + options || {} + ); + + // The browser's "helpful" auto-complete gets in the way. + this.element.writeAttribute("autocomplete", "off"); + this.element.setValue(''); + + // Hitting "enter" should do nothing. + this.element.up('form').observe("submit", Event.stop); + + this.menu = this.options.menu; + this.links = this.menu.select('a'); + + this.resultsElement = this.options.resultsElement; + + this.observers = { + filter: this.filter.bind(this), + keydown: this.keydown.bind(this), + keyup: this.keyup.bind(this) + }; + + this.menu.setStyle({ opacity: 0.9 }); + this.addObservers(); + }, + + addObservers: function() { + this.element.observe('keyup', this.observers.filter); + }, + + // Called whenever the list of results needs to update as a result of a + // changed search key. + filter: function(event) { + // Clear the text box on ESC. + if (event.keyCode && event.keyCode === Event.KEY_ESC) { + this.element.setValue(''); + } + + if (PDoc.Sidebar.Filterer.INTERCEPT_KEYS.include(event.keyCode)) + return; + + // If there's nothing in the text box, clear the results list. + var value = $F(this.element).strip().toLowerCase(); + if (value === '') { + this.emptyResults(); + this.hideResults(); + return; + } + + var urls = this.findURLs(value); + this.buildResults(urls); + }, + + setSearchValue: function(value) { + this.element.setValue(value); + if (value.strip() === "") { + PDoc.Sidebar.Tabs.setActiveTab(0); + return; + } + this.buildResults(this.findURLs(value)); + }, + + // Given a key, finds all the PDoc objects that match. + findURLs: function(str) { + var results = []; + for (var name in PDoc.elements) { + if (name.toLowerCase().include(str.toLowerCase())) + results.push(PDoc.elements[name]); + } + return results; + }, + + buildResults: function(results) { + this.emptyResults(); + + results.each( function(result) { + var li = this._buildResult(result); + this.resultsElement.appendChild(li); + }, this); + this.showResults(); + }, + + _buildResult: function(obj) { + var li = new Element('li', { 'class': 'menu-item' }); + var a = new Element('a', { + 'class': obj.type.gsub(/\s/, '-'), + 'href': PDoc.pathPrefix + obj.path + }).update(obj.name); + + li.appendChild(a); + return li; + }, + + emptyResults: function() { + this.resultsElement.update(); + }, + + hideResults: function() { + PDoc.Sidebar.Tabs.setActiveTab(0); + //this.resultsElement.hide(); + document.stopObserving('keydown', this.observers.keydown); + document.stopObserving('keyup', this.observers.keyup); + }, + + showResults: function() { + PDoc.Sidebar.Tabs.setActiveTab(1); + //this.resultsElement.show(); + document.stopObserving('keydown', this.observers.keydown); + this.element.stopObserving('keyup', this.observers.keyup); + this.element.observe('keydown', this.observers.keydown); + document.observe('keyup', this.observers.keyup); + }, + + keydown: function(event) { + if (!PDoc.Sidebar.Filterer.INTERCEPT_KEYS.include(event.keyCode)) + return; + + // Also ignore if any modifier keys are present. + if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) + return; + + event.stop(); + + if (event.keyCode === Event.KEY_RETURN) { + // Follow the highlighted item, unless there is none. + if (!this.highlighted) return; + var a = this.highlighted.down('a'); + if (a) { + window.location.href = a.href; + } + } else if ([Event.KEY_UP, Event.KEY_DOWN].include(event.keyCode)) { + // Is an arrow key. + var direction = (Event.KEY_DOWN === event.keyCode) ? 1 : -1; + this.highlighted = this.moveHighlight(direction); + + if (!Prototype.Browser.WebKit) { + // If up/down key is held down, list should keep scrolling. + // WebKit does this automatically because it fires the keydown + // event over and over. + this._scrollTimer = window.setTimeout( + this.scrollList.bind(this, direction), 1000); + } + } + }, + + keyup: function(event) { + if (this._scrollTimer) { + window.clearTimeout(this._scrollTimer); + } + }, + + moveHighlight: function(direction) { + if (!this.highlighted) { + // If there is none, highlight the first result. + this.highlighted = + this.resultsElement.down('li').addClassName('highlighted'); + } else { + var method = (direction === 1) ? 'next' : 'previous'; + this.highlighted.removeClassName('highlighted'); + var adjacent = this.highlighted[method]('li'); + // If there isn't an adjacent one, we're at the top or bottom + // of the list. Flip it. + if (!adjacent) { + adjacent = method == 'next' ? this.resultsElement.down('li') : + this.resultsElement.down('li:last-of-type'); + } + adjacent.addClassName('highlighted'); + this.highlighted = adjacent; + } + + var h = this.highlighted, r = this.resultsElement; + + var distanceToBottom = h.offsetTop + h.offsetHeight; + if (distanceToBottom > (r.offsetHeight + r.scrollTop)) { + // Item is below the visible frame. + r.scrollTop = distanceToBottom - r.offsetHeight; + } else if (h.offsetTop < r.scrollTop) { + // Item is above the visible frame. + r.scrollTop = h.offsetTop; + } + + return this.highlighted; + }, + + scrollList: function(direction) { + this.moveHighlight(direction); + this._scrollTimer = window.setTimeout( + this.scrollList.bind(this, direction), 100); + } +}); + +Object.extend(PDoc.Sidebar.Filterer, { + INTERCEPT_KEYS: [Event.KEY_UP, Event.KEY_DOWN, Event.KEY_RETURN], + DEFAULT_OPTIONS: { + interval: 0.1, + resultsElement: '.search-results' + } +}); + + +Form.GhostedField = Class.create({ + initialize: function(element, title, options) { + options = options || {}; + + this.element = $(element); + this.title = title; + + this.isGhosted = true; + + if (options.cloak) { + + // Wrap the native getValue function so that it never returns the + // ghosted value. This is optional because it presumes the ghosted + // value isn't valid input for the field. + this.element.getValue = this.element.getValue.wrap(this.wrappedGetValue.bind(this)); + } + + this.addObservers(); + + this.onBlur(); + }, + + wrappedGetValue: function($proceed) { + var value = $proceed(); + return value === this.title ? "" : value; + }, + + addObservers: function() { + this.element.observe('focus', this.onFocus.bind(this)); + this.element.observe('blur', this.onBlur.bind(this)); + + var form = this.element.up('form'); + if (form) { + form.observe('submit', this.onSubmit.bind(this)); + } + + // Firefox's bfcache means that form fields need to be re-initialized + // when you hit the "back" button to return to the page. + if (Prototype.Browser.Gecko) { + window.addEventListener('pageshow', this.onBlur.bind(this), false); + } + }, + + onFocus: function() { + if (this.isGhosted) { + this.element.setValue(''); + this.setGhosted(false); + } + }, + + onBlur: function() { + var value = this.element.getValue(); + if (value.blank() || value == this.title) { + this.setGhosted(true); + } else { + this.setGhosted(false); + } + }, + + setGhosted: function(isGhosted) { + this.isGhosted = isGhosted; + this.element[isGhosted ? 'addClassName' : 'removeClassName']('ghosted'); + if (isGhosted) { + this.element.setValue(this.title); + } + }, + + // Hook into the enclosing form's `onsubmit` event so that we clear any + // ghosted text before the form is sent. + onSubmit: function() { + if (this.isGhosted) { + this.element.setValue(''); + } + } +}); + +document.observe('dom:loaded', function() { + PDoc.Sidebar.Tabs = new Control.Tabs($('sidebar_tabs')); + + var searchField = $('search'); + + if (searchField) { + var filterer = new PDoc.Sidebar.Filterer(searchField, { + menu: $('api_menu'), + resultsElement: $('search_results') + }); + searchField.store('filterer', filterer); + } + + // Prevent horizontal scrolling in scrollable sidebar areas. + $$('.scrollable').invoke('observe', 'scroll', function() { + this.scrollLeft = 0; + }); + + var sidebarState = Cookie.get('sidebar_state'); + if (sidebarState) { + PDoc.Sidebar.restore(sidebarState); + } + + new Form.GhostedField(searchField, searchField.getAttribute('title'), + { cloak: true }); +}); + +Event.observe(window, 'unload', function() { + Cookie.set('sidebar_state', PDoc.Sidebar.serialize()); +}); \ No newline at end of file diff --git a/doc/1.7_rc1/javascripts/controls.js b/doc/1.7_rc1/javascripts/controls.js new file mode 100644 index 000000000..fbc4418b8 --- /dev/null +++ b/doc/1.7_rc1/javascripts/controls.js @@ -0,0 +1,963 @@ +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) +// Contributors: +// Richard Livsey +// Rahul Bhargava +// Rob Wills +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// Autocompleter.Base handles all the autocompletion functionality +// that's independent of the data source for autocompletion. This +// includes drawing the autocompletion menu, observing keyboard +// and mouse events, and similar. +// +// Specific autocompleters need to provide, at the very least, +// a getUpdatedChoices function that will be invoked every time +// the text inside the monitored textbox changes. This method +// should get the text for which to provide autocompletion by +// invoking this.getToken(), NOT by directly accessing +// this.element.value. This is to allow incremental tokenized +// autocompletion. Specific auto-completion logic (AJAX, etc) +// belongs in getUpdatedChoices. +// +// Tokenized incremental autocompletion is enabled automatically +// when an autocompleter is instantiated with the 'tokens' option +// in the options parameter, e.g.: +// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); +// will incrementally autocomplete with a comma as the token. +// Additionally, ',' in the above example can be replaced with +// a token array, e.g. { tokens: [',', '\n'] } which +// enables autocompletion on multiple tokens. This is most +// useful when one of the tokens is \n (a newline), as it +// allows smart autocompletion after linebreaks. + +if(typeof Effect == 'undefined') + throw("controls.js requires including script.aculo.us' effects.js library"); + +var Autocompleter = { } +Autocompleter.Base = Class.create({ + baseInitialize: function(element, update, options) { + element = $(element) + this.element = element; + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; + this.entryCount = 0; + this.oldElementValue = this.element.value; + + if(this.setOptions) + this.setOptions(options); + else + this.options = options || { }; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || + function(element, update){ + if(!update.style.position || update.style.position=='absolute') { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update,{duration:0.15}); + }; + this.options.onHide = this.options.onHide || + function(element, update){ new Effect.Fade(update,{duration:0.15}) }; + + if(typeof(this.options.tokens) == 'string') + this.options.tokens = new Array(this.options.tokens); + // Force carriage returns as token delimiters anyway + if (!this.options.tokens.include('\n')) + this.options.tokens.push('\n'); + + this.observer = null; + + this.element.setAttribute('autocomplete','off'); + + Element.hide(this.update); + + Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() { + if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); + if(!this.iefix && + (Prototype.Browser.IE) && + (Element.getStyle(this.update, 'position')=='absolute')) { + new Insertion.After(this.update, + ''); + this.iefix = $(this.update.id+'_iefix'); + } + if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() { + this.stopIndicator(); + if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); + if(this.iefix) Element.hide(this.iefix); + }, + + startIndicator: function() { + if(this.options.indicator) Element.show(this.options.indicator); + }, + + stopIndicator: function() { + if(this.options.indicator) Element.hide(this.options.indicator); + }, + + onKeyPress: function(event) { + if(this.active) + switch(event.keyCode) { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + Event.stop(event); + return; + } + else + if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; + + this.changed = true; + this.hasFocus = true; + + if(this.observer) clearTimeout(this.observer); + this.observer = + setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); + }, + + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function(event) { + var element = Event.findElement(event, 'LI'); + if(this.index != element.autocompleteIndex) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function(event) { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; + this.selectEntry(); + this.hide(); + }, + + onBlur: function(event) { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() { + if(this.entryCount > 0) { + for (var i = 0; i < this.entryCount; i++) + this.index==i ? + Element.addClassName(this.getEntry(i),"selected") : + Element.removeClassName(this.getEntry(i),"selected"); + if(this.hasFocus) { + this.show(); + this.active = true; + } + } else { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() { + if(this.index > 0) this.index-- + else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() { + if(this.index < this.entryCount-1) this.index++ + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function(index) { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() { + return this.getEntry(this.index); + }, + + selectEntry: function() { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function(selectedElement) { + if (this.options.updateElement) { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if (this.options.select) { + var nodes = $(selectedElement).select('.' + this.options.select) || []; + if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); + } else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var bounds = this.getTokenBounds(); + if (bounds[0] != -1) { + var newValue = this.element.value.substr(0, bounds[0]); + var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); + if (whitespace) + newValue += whitespace[0]; + this.element.value = newValue + value + this.element.value.substr(bounds[1]); + } else { + this.element.value = value; + } + this.oldElementValue = this.element.value; + this.element.focus(); + + if (this.options.afterUpdateElement) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function(choices) { + if(!this.changed && this.hasFocus) { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.down()); + + if(this.update.firstChild && this.update.down().childNodes) { + this.entryCount = + this.update.down().childNodes.length; + for (var i = 0; i < this.entryCount; i++) { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } else { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if(this.entryCount==1 && this.options.autoSelect) { + this.selectEntry(); + this.hide(); + } else { + this.render(); + } + } + }, + + addObservers: function(element) { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() { + this.changed = false; + this.tokenBounds = null; + if(this.getToken().length>=this.options.minChars) { + this.getUpdatedChoices(); + } else { + this.active = false; + this.hide(); + } + this.oldElementValue = this.element.value; + }, + + getToken: function() { + var bounds = this.getTokenBounds(); + return this.element.value.substring(bounds[0], bounds[1]).strip(); + }, + + getTokenBounds: function() { + if (null != this.tokenBounds) return this.tokenBounds; + var value = this.element.value; + if (value.strip().empty()) return [-1, 0]; + var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); + var offset = (diff == this.oldElementValue.length ? 1 : 0); + var prevTokenPos = -1, nextTokenPos = value.length; + var tp; + for (var index = 0, l = this.options.tokens.length; index < l; ++index) { + tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); + if (tp > prevTokenPos) prevTokenPos = tp; + tp = value.indexOf(this.options.tokens[index], diff + offset); + if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; + } + return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); + } +}); + +Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { + var boundary = Math.min(newS.length, oldS.length); + for (var index = 0; index < boundary; ++index) + if (newS[index] != oldS[index]) + return index; + return boundary; +}; + +Ajax.Autocompleter = Class.create(Autocompleter.Base, { + initialize: function(element, update, url, options) { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() { + this.startIndicator(); + + var entry = encodeURIComponent(this.options.paramName) + '=' + + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? + this.options.callback(this.element, entry) : entry; + + if(this.options.defaultParams) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function(request) { + this.updateChoices(request.responseText); + } +}); + +// The local array autocompleter. Used when you'd prefer to +// inject an array of autocompletion options into the page, rather +// than sending out Ajax queries, which can be quite slow sometimes. +// +// The constructor takes four parameters. The first two are, as usual, +// the id of the monitored textbox, and id of the autocompletion menu. +// The third is the array you want to autocomplete from, and the fourth +// is the options block. +// +// Extra local autocompletion options: +// - choices - How many autocompletion choices to offer +// +// - partialSearch - If false, the autocompleter will match entered +// text only at the beginning of strings in the +// autocomplete array. Defaults to true, which will +// match text at the beginning of any *word* in the +// strings in the autocomplete array. If you want to +// search anywhere in the string, additionally set +// the option fullSearch to true (default: off). +// +// - fullSsearch - Search anywhere in autocomplete array strings. +// +// - partialChars - How many characters to enter before triggering +// a partial match (unlike minChars, which defines +// how many characters are required to do any match +// at all). Defaults to 2. +// +// - ignoreCase - Whether to ignore case when autocompleting. +// Defaults to true. +// +// It's possible to pass in a custom function as the 'selector' +// option, if you prefer to write your own autocompletion logic. +// In that case, the other options above will not apply unless +// you support them. + +Autocompleter.Local = Class.create(Autocompleter.Base, { + initialize: function(element, update, array, options) { + this.baseInitialize(element, update, options); + this.options.array = array; + }, + + getUpdatedChoices: function() { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function(options) { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function(instance) { + var ret = []; // Beginning matches + var partial = []; // Inside matches + var entry = instance.getToken(); + var count = 0; + + for (var i = 0; i < instance.options.array.length && + ret.length < instance.options.choices ; i++) { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase()) : + elem.indexOf(entry); + + while (foundPos != -1) { + if (foundPos == 0 && elem.length != entry.length) { + ret.push("
  • " + elem.substr(0, entry.length) + "" + + elem.substr(entry.length) + "
  • "); + break; + } else if (entry.length >= instance.options.partialChars && + instance.options.partialSearch && foundPos != -1) { + if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { + partial.push("
  • " + elem.substr(0, foundPos) + "" + + elem.substr(foundPos, entry.length) + "" + elem.substr( + foundPos + entry.length) + "
  • "); + break; + } + } + + foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : + elem.indexOf(entry, foundPos + 1); + + } + } + if (partial.length) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) + return "
      " + ret.join('') + "
    "; + } + }, options || { }); + } +}); + +// AJAX in-place editor and collection editor +// Full rewrite by Christophe Porteneuve (April 2007). + +// Use this if you notice weird scrolling problems on some browsers, +// the DOM might be a bit confused when this gets called so do this +// waits 1 ms (with setTimeout) until it does the activation +Field.scrollFreeActivate = function(field) { + setTimeout(function() { + Field.activate(field); + }, 1); +} + +Ajax.InPlaceEditor = Class.create({ + initialize: function(element, url, options) { + this.url = url; + this.element = element = $(element); + this.prepareOptions(); + this._controls = { }; + arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! + Object.extend(this.options, options || { }); + if (!this.options.formId && this.element.id) { + this.options.formId = this.element.id + '-inplaceeditor'; + if ($(this.options.formId)) + this.options.formId = ''; + } + if (this.options.externalControl) + this.options.externalControl = $(this.options.externalControl); + if (!this.options.externalControl) + this.options.externalControlOnly = false; + this._originalBackground = this.element.getStyle('background-color') || 'transparent'; + this.element.title = this.options.clickToEditText; + this._boundCancelHandler = this.handleFormCancellation.bind(this); + this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); + this._boundFailureHandler = this.handleAJAXFailure.bind(this); + this._boundSubmitHandler = this.handleFormSubmission.bind(this); + this._boundWrapperHandler = this.wrapUp.bind(this); + this.registerListeners(); + }, + checkForEscapeOrReturn: function(e) { + if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; + if (Event.KEY_ESC == e.keyCode) + this.handleFormCancellation(e); + else if (Event.KEY_RETURN == e.keyCode) + this.handleFormSubmission(e); + }, + createControl: function(mode, handler, extraClasses) { + var control = this.options[mode + 'Control']; + var text = this.options[mode + 'Text']; + if ('button' == control) { + var btn = document.createElement('input'); + btn.type = 'submit'; + btn.value = text; + btn.className = 'editor_' + mode + '_button'; + if ('cancel' == mode) + btn.onclick = this._boundCancelHandler; + this._form.appendChild(btn); + this._controls[mode] = btn; + } else if ('link' == control) { + var link = document.createElement('a'); + link.href = '#'; + link.appendChild(document.createTextNode(text)); + link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; + link.className = 'editor_' + mode + '_link'; + if (extraClasses) + link.className += ' ' + extraClasses; + this._form.appendChild(link); + this._controls[mode] = link; + } + }, + createEditField: function() { + var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); + var fld; + if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { + fld = document.createElement('input'); + fld.type = 'text'; + var size = this.options.size || this.options.cols || 0; + if (0 < size) fld.size = size; + } else { + fld = document.createElement('textarea'); + fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); + fld.cols = this.options.cols || 40; + } + fld.name = this.options.paramName; + fld.value = text; // No HTML breaks conversion anymore + fld.className = 'editor_field'; + if (this.options.submitOnBlur) + fld.onblur = this._boundSubmitHandler; + this._controls.editor = fld; + if (this.options.loadTextURL) + this.loadExternalText(); + this._form.appendChild(this._controls.editor); + }, + createForm: function() { + var ipe = this; + function addText(mode, condition) { + var text = ipe.options['text' + mode + 'Controls']; + if (!text || condition === false) return; + ipe._form.appendChild(document.createTextNode(text)); + }; + this._form = $(document.createElement('form')); + this._form.id = this.options.formId; + this._form.addClassName(this.options.formClassName); + this._form.onsubmit = this._boundSubmitHandler; + this.createEditField(); + if ('textarea' == this._controls.editor.tagName.toLowerCase()) + this._form.appendChild(document.createElement('br')); + if (this.options.onFormCustomization) + this.options.onFormCustomization(this, this._form); + addText('Before', this.options.okControl || this.options.cancelControl); + this.createControl('ok', this._boundSubmitHandler); + addText('Between', this.options.okControl && this.options.cancelControl); + this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); + addText('After', this.options.okControl || this.options.cancelControl); + }, + destroy: function() { + if (this._oldInnerHTML) + this.element.innerHTML = this._oldInnerHTML; + this.leaveEditMode(); + this.unregisterListeners(); + }, + enterEditMode: function(e) { + if (this._saving || this._editing) return; + this._editing = true; + this.triggerCallback('onEnterEditMode'); + if (this.options.externalControl) + this.options.externalControl.hide(); + this.element.hide(); + this.createForm(); + this.element.parentNode.insertBefore(this._form, this.element); + if (!this.options.loadTextURL) + this.postProcessEditField(); + if (e) Event.stop(e); + }, + enterHover: function(e) { + if (this.options.hoverClassName) + this.element.addClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onEnterHover'); + }, + getText: function() { + return this.element.innerHTML; + }, + handleAJAXFailure: function(transport) { + this.triggerCallback('onFailure', transport); + if (this._oldInnerHTML) { + this.element.innerHTML = this._oldInnerHTML; + this._oldInnerHTML = null; + } + }, + handleFormCancellation: function(e) { + this.wrapUp(); + if (e) Event.stop(e); + }, + handleFormSubmission: function(e) { + var form = this._form; + var value = $F(this._controls.editor); + this.prepareSubmission(); + var params = this.options.callback(form, value) || ''; + if (Object.isString(params)) + params = params.toQueryParams(); + params.editorId = this.element.id; + if (this.options.htmlResponse) { + var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Updater({ success: this.element }, this.url, options); + } else { + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.url, options); + } + if (e) Event.stop(e); + }, + leaveEditMode: function() { + this.element.removeClassName(this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + if (this.options.externalControl) + this.options.externalControl.show(); + this._saving = false; + this._editing = false; + this._oldInnerHTML = null; + this.triggerCallback('onLeaveEditMode'); + }, + leaveHover: function(e) { + if (this.options.hoverClassName) + this.element.removeClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onLeaveHover'); + }, + loadExternalText: function() { + this._form.addClassName(this.options.loadingClassName); + this._controls.editor.disabled = true; + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._form.removeClassName(this.options.loadingClassName); + var text = transport.responseText; + if (this.options.stripLoadedTextTags) + text = text.stripTags(); + this._controls.editor.value = text; + this._controls.editor.disabled = false; + this.postProcessEditField(); + }.bind(this), + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + postProcessEditField: function() { + var fpc = this.options.fieldPostCreation; + if (fpc) + $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); + }, + prepareOptions: function() { + this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); + Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); + [this._extraDefaultOptions].flatten().compact().each(function(defs) { + Object.extend(this.options, defs); + }.bind(this)); + }, + prepareSubmission: function() { + this._saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + registerListeners: function() { + this._listeners = { }; + var listener; + $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { + listener = this[pair.value].bind(this); + this._listeners[pair.key] = listener; + if (!this.options.externalControlOnly) + this.element.observe(pair.key, listener); + if (this.options.externalControl) + this.options.externalControl.observe(pair.key, listener); + }.bind(this)); + }, + removeForm: function() { + if (!this._form) return; + this._form.remove(); + this._form = null; + this._controls = { }; + }, + showSaving: function() { + this._oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + this.element.addClassName(this.options.savingClassName); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + }, + triggerCallback: function(cbName, arg) { + if ('function' == typeof this.options[cbName]) { + this.options[cbName](this, arg); + } + }, + unregisterListeners: function() { + $H(this._listeners).each(function(pair) { + if (!this.options.externalControlOnly) + this.element.stopObserving(pair.key, pair.value); + if (this.options.externalControl) + this.options.externalControl.stopObserving(pair.key, pair.value); + }.bind(this)); + }, + wrapUp: function(transport) { + this.leaveEditMode(); + // Can't use triggerCallback due to backward compatibility: requires + // binding + direct element + this._boundComplete(transport, this.element); + } +}); + +Object.extend(Ajax.InPlaceEditor.prototype, { + dispose: Ajax.InPlaceEditor.prototype.destroy +}); + +Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { + initialize: function($super, element, url, options) { + this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; + $super(element, url, options); + }, + + createEditField: function() { + var list = document.createElement('select'); + list.name = this.options.paramName; + list.size = 1; + this._controls.editor = list; + this._collection = this.options.collection || []; + if (this.options.loadCollectionURL) + this.loadCollection(); + else + this.checkForExternalText(); + this._form.appendChild(this._controls.editor); + }, + + loadCollection: function() { + this._form.addClassName(this.options.loadingClassName); + this.showLoadingText(this.options.loadingCollectionText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + var js = transport.responseText.strip(); + if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check + throw 'Server returned an invalid collection representation.'; + this._collection = eval(js); + this.checkForExternalText(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadCollectionURL, options); + }, + + showLoadingText: function(text) { + this._controls.editor.disabled = true; + var tempOption = this._controls.editor.firstChild; + if (!tempOption) { + tempOption = document.createElement('option'); + tempOption.value = ''; + this._controls.editor.appendChild(tempOption); + tempOption.selected = true; + } + tempOption.update((text || '').stripScripts().stripTags()); + }, + + checkForExternalText: function() { + this._text = this.getText(); + if (this.options.loadTextURL) + this.loadExternalText(); + else + this.buildOptionList(); + }, + + loadExternalText: function() { + this.showLoadingText(this.options.loadingText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._text = transport.responseText.strip(); + this.buildOptionList(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + + buildOptionList: function() { + this._form.removeClassName(this.options.loadingClassName); + this._collection = this._collection.map(function(entry) { + return 2 === entry.length ? entry : [entry, entry].flatten(); + }); + var marker = ('value' in this.options) ? this.options.value : this._text; + var textFound = this._collection.any(function(entry) { + return entry[0] == marker; + }.bind(this)); + this._controls.editor.update(''); + var option; + this._collection.each(function(entry, index) { + option = document.createElement('option'); + option.value = entry[0]; + option.selected = textFound ? entry[0] == marker : 0 == index; + option.appendChild(document.createTextNode(entry[1])); + this._controls.editor.appendChild(option); + }.bind(this)); + this._controls.editor.disabled = false; + Field.scrollFreeActivate(this._controls.editor); + } +}); + +//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** +//**** This only exists for a while, in order to let **** +//**** users adapt to the new API. Read up on the new **** +//**** API and convert your code to it ASAP! **** + +Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { + if (!options) return; + function fallback(name, expr) { + if (name in options || expr === undefined) return; + options[name] = expr; + }; + fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : + options.cancelLink == options.cancelButton == false ? false : undefined))); + fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : + options.okLink == options.okButton == false ? false : undefined))); + fallback('highlightColor', options.highlightcolor); + fallback('highlightEndColor', options.highlightendcolor); +}; + +Object.extend(Ajax.InPlaceEditor, { + DefaultOptions: { + ajaxOptions: { }, + autoRows: 3, // Use when multi-line w/ rows == 1 + cancelControl: 'link', // 'link'|'button'|false + cancelText: 'cancel', + clickToEditText: 'Click to edit', + externalControl: null, // id|elt + externalControlOnly: false, + fieldPostCreation: 'activate', // 'activate'|'focus'|false + formClassName: 'inplaceeditor-form', + formId: null, // id|elt + highlightColor: '#ffff99', + highlightEndColor: '#ffffff', + hoverClassName: '', + htmlResponse: true, + loadingClassName: 'inplaceeditor-loading', + loadingText: 'Loading...', + okControl: 'button', // 'link'|'button'|false + okText: 'ok', + paramName: 'value', + rows: 1, // If 1 and multi-line, uses autoRows + savingClassName: 'inplaceeditor-saving', + savingText: 'Saving...', + size: 0, + stripLoadedTextTags: false, + submitOnBlur: false, + textAfterControls: '', + textBeforeControls: '', + textBetweenControls: '' + }, + DefaultCallbacks: { + callback: function(form) { + return Form.serialize(form); + }, + onComplete: function(transport, element) { + // For backward compatibility, this one is bound to the IPE, and passes + // the element directly. It was too often customized, so we don't break it. + new Effect.Highlight(element, { + startcolor: this.options.highlightColor, keepBackgroundImage: true }); + }, + onEnterEditMode: null, + onEnterHover: function(ipe) { + ipe.element.style.backgroundColor = ipe.options.highlightColor; + if (ipe._effect) + ipe._effect.cancel(); + }, + onFailure: function(transport, ipe) { + alert('Error communication with the server: ' + transport.responseText.stripTags()); + }, + onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. + onLeaveEditMode: null, + onLeaveHover: function(ipe) { + ipe._effect = new Effect.Highlight(ipe.element, { + startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, + restorecolor: ipe._originalBackground, keepBackgroundImage: true + }); + } + }, + Listeners: { + click: 'enterEditMode', + keydown: 'checkForEscapeOrReturn', + mouseover: 'enterHover', + mouseout: 'leaveHover' + } +}); + +Ajax.InPlaceCollectionEditor.DefaultOptions = { + loadingCollectionText: 'Loading options...' +}; + +// Delayed observer, like Form.Element.Observer, +// but waits for delay after last key input +// Ideal for live-search fields + +Form.Element.DelayedObserver = Class.create({ + initialize: function(element, delay, callback) { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function(event) { + if(this.lastValue == $F(this.element)) return; + if(this.timer) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() { + this.timer = null; + this.callback(this.element, $F(this.element)); + } +}); diff --git a/doc/1.7_rc1/javascripts/effects.js b/doc/1.7_rc1/javascripts/effects.js new file mode 100644 index 000000000..718a88d21 --- /dev/null +++ b/doc/1.7_rc1/javascripts/effects.js @@ -0,0 +1,1120 @@ +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if (this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if (this.slice(0,1) == '#') { + if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if (this.length==7) color = this.toLowerCase(); + } + } + return (color.length==7 ? color : (arguments[0] || this)); +}; + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +}; + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +}; + +Element.setContentZoom = function(element, percent) { + element = $(element); + element.setStyle({fontSize: (percent/100) + 'em'}); + if (Prototype.Browser.WebKit) window.scrollBy(0,0); + return element; +}; + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +}; + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + Transitions: { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + 0.5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + return pos > 1 ? 1 : pos; + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; + }, + pulse: function(pos, pulses) { + pulses = pulses || 5; + return ( + ((pos % (1/pulses)) * pulses).round() == 0 ? + ((pos * pulses * 2) - (pos * pulses * 2).floor()) : + 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) + ); + }, + spring: function(pos) { + return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } + }, + DefaultOptions: { + duration: 1.0, // seconds + fps: 100, // 100= assume 66fps max. + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' + }, + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; + + element = $(element); + $A(element.childNodes).each( function(child) { + if (child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + new Element('span', {style: tagifyStyle}).update( + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if (((typeof element == 'object') || + Object.isFunction(element)) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || { }); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || { }); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(Enumerable, { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = Object.isString(effect.options.queue) ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if (!this.interval) + this.interval = setInterval(this.loop.bind(this), 15); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if (this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + for(var i=0, len=this.effects.length;i= this.startOn) { + if (timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if (this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / this.totalTime, + frame = (pos * this.totalFrames).round(); + if (frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + cancel: function() { + if (!this.options.sync) + Effect.Queues.get(Object.isString(this.options.queue) ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if (this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + var data = $H(); + for(property in this) + if (!Object.isFunction(this[property])) data.set(property, this[property]); + return '#'; + } +}); + +Effect.Parallel = Class.create(Effect.Base, { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if (effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Tween = Class.create(Effect.Base, { + initialize: function(object, from, to) { + object = Object.isString(object) ? $(object) : object; + var args = $A(arguments), method = args.last(), + options = args.length == 5 ? args[3] : null; + this.method = Object.isFunction(method) ? method.bind(object) : + Object.isFunction(object[method]) ? object[method].bind(object) : + function(value) { object[method] = value }; + this.start(Object.extend({ from: from, to: to }, options || { })); + }, + update: function(position) { + this.method(position); + } +}); + +Effect.Event = Class.create(Effect.Base, { + initialize: function() { + this.start(Object.extend({ duration: 0 }, arguments[0] || { })); + }, + update: Prototype.emptyFunction +}); + +Effect.Opacity = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || { }); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if (this.options.mode == 'absolute') { + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: (this.options.x * position + this.originalLeft).round() + 'px', + top: (this.options.y * position + this.originalTop).round() + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); +}; + +Effect.Scale = Class.create(Effect.Base, { + initialize: function(element, percent) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or { } with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || { }); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = { }; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if (fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if (this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if (/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if (!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if (this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = { }; + if (this.options.scaleX) d.width = width.round() + 'px'; + if (this.options.scaleY) d.height = height.round() + 'px'; + if (this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if (this.elementPositioning == 'absolute') { + if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if (this.options.scaleY) d.top = -topd + 'px'; + if (this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if (this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { }; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } + if (!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if (!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = function(element) { + var options = arguments[1] || { }, + scrollOffsets = document.viewport.getScrollOffsets(), + elementOffsets = $(element).cumulativeOffset(), + max = document.viewport.getScrollOffsets[0] - document.viewport.getHeight(); + + if (options.offset) elementOffsets[1] += options.offset; + + return new Effect.Tween(null, + scrollOffsets.top, + elementOffsets[1] > max ? max : elementOffsets[1], + options, + function(p){ scrollTo(scrollOffsets.left, p.round()) } + ); +}; + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if (effect.options.to!=0) return; + effect.element.hide().setStyle({opacity: oldOpacity}); + } + }, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from).show(); + }}, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element) + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().setStyle(oldStyle); } + }, arguments[1] || { }) + ); +}; + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }, arguments[1] || { }) + ); +}; + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || { })); +}; + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); + } + }) + } + }, arguments[1] || { })); +}; + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); + } + }, arguments[1] || { })); +}; + +Effect.Shake = function(element) { + element = $(element); + var options = Object.extend({ + distance: 20, + duration: 0.5 + }, arguments[1] || {}); + var distance = parseFloat(options.distance); + var split = parseFloat(options.duration) / 10.0; + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { + effect.element.undoPositioned().setStyle(oldStyle); + }}) }}) }}) }}) }}) }}); +}; + +Effect.SlideDown = function(element) { + element = $(element).cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || { }) + ); +}; + +Effect.SlideUp = function(element) { + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); + } + }, arguments[1] || { }) + ); +}; + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }); +}; + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide().makeClipping().makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); + } + }, options) + ) + } + }); +}; + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } + }, options) + ); +}; + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || { }; + var oldOpacity = element.getInlineOpacity(); + var transition = options.transition || Effect.Transitions.sinoidal; + var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; + reverser.bind(transition); + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 2.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +}; + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + element.makeClipping(); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().setStyle(oldStyle); + } }); + }}, arguments[1] || { })); +}; + +Effect.Morph = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: { } + }, arguments[1] || { }); + + if (!Object.isString(options.style)) this.style = $H(options.style); + else { + if (options.style.include(':')) + this.style = options.style.parseStyle(); + else { + this.element.addClassName(options.style); + this.style = $H(this.element.getStyles()); + this.element.removeClassName(options.style); + var css = this.element.getStyles(); + this.style = this.style.reject(function(style) { + return style.value == css[style.key]; + }); + options.afterFinishInternal = function(effect) { + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + effect.element.style[transform.style] = ''; + }); + } + } + } + this.start(options); + }, + + setup: function(){ + function parseColor(color){ + if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ) + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0], value = pair[1], unit = null; + + if (value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if (property == 'opacity') { + value = parseFloat(value); + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if (Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } + + var originalValue = this.element.getStyle(property); + return { + style: property.camelize(), + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }; + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ) + }); + }, + update: function(position) { + var style = { }, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : + (transform.originalValue + + (transform.targetValue - transform.originalValue) * position).toFixed(3) + + (transform.unit === null ? '' : transform.unit); + this.element.setStyle(style, true); + } +}); + +Effect.Transform = Class.create({ + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || { }; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + track = $H(track); + var data = track.values().first(); + this.tracks.push($H({ + ids: track.keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); + var elements = [$(ids) || $$(ids)].flatten(); + return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.__parseStyleElement = document.createElement('div'); +String.prototype.parseStyle = function(){ + var style, styleRules = $H(); + if (Prototype.Browser.WebKit) + style = new Element('div',{style:this}).style; + else { + String.__parseStyleElement.innerHTML = '
    '; + style = String.__parseStyleElement.childNodes[0].style; + } + + Element.CSS_PROPERTIES.each(function(property){ + if (style[property]) styleRules.set(property, style[property]); + }); + + if (Prototype.Browser.IE && this.include('opacity')) + styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); + + return styleRules; +}; + +if (document.defaultView && document.defaultView.getComputedStyle) { + Element.getStyles = function(element) { + var css = document.defaultView.getComputedStyle($(element), null); + return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { + styles[property] = css[property]; + return styles; + }); + }; +} else { + Element.getStyles = function(element) { + element = $(element); + var css = element.currentStyle, styles; + styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { + results[property] = css[property]; + return results; + }); + if (!styles.opacity) styles.opacity = element.getOpacity(); + return styles; + }; +}; + +Effect.Methods = { + morph: function(element, style) { + element = $(element); + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); + return element; + }, + visualEffect: function(element, effect, options) { + element = $(element) + var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[klass](element, options); + return element; + }, + highlight: function(element, options) { + element = $(element); + new Effect.Highlight(element, options); + return element; + } +}; + +$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ + 'pulsate shake puff squish switchOff dropOut').each( + function(effect) { + Effect.Methods[effect] = function(element, options){ + element = $(element); + Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); + return element; + } + } +); + +$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( + function(f) { Effect.Methods[f] = Element[f]; } +); + +Element.addMethods(Effect.Methods); diff --git a/doc/1.7_rc1/javascripts/item_index.js b/doc/1.7_rc1/javascripts/item_index.js new file mode 100644 index 000000000..6bdbdb860 --- /dev/null +++ b/doc/1.7_rc1/javascripts/item_index.js @@ -0,0 +1,458 @@ +if (!window.PDoc) window.PDoc = {}; +PDoc.elements = { + 'Element#remove': { 'name': 'Element#remove', 'type': 'instance method', 'path': 'dom/element/prototype/remove' }, +'Form.Element.serialize': { 'name': 'Form.Element.serialize', 'type': 'class method', 'path': 'dom/form/element/serialize' }, +'Hash#toTemplateReplacements': { 'name': 'Hash#toTemplateReplacements', 'type': 'instance method', 'path': 'language/hash/prototype/totemplatereplacements' }, +'Enumerable#zip': { 'name': 'Enumerable#zip', 'type': 'instance method', 'path': 'language/enumerable/prototype/zip' }, +'String': { 'name': 'String', 'type': 'class', 'path': 'language/string' }, +'Element.descendantOf': { 'name': 'Element.descendantOf', 'type': 'class method', 'path': 'dom/element/descendantof' }, +'Element#immediateDescendants': { 'name': 'Element#immediateDescendants', 'type': 'instance method', 'path': 'dom/element/prototype/immediatedescendants' }, +'String#extractScripts': { 'name': 'String#extractScripts', 'type': 'instance method', 'path': 'language/string/prototype/extractscripts' }, +'Event.Handler#start': { 'name': 'Event.Handler#start', 'type': 'instance property', 'path': 'dom/event/handler/prototype/start' }, +'Element#makePositioned': { 'name': 'Element#makePositioned', 'type': 'instance method', 'path': 'dom/element/prototype/makepositioned' }, +'Element.stopObserving': { 'name': 'Element.stopObserving', 'type': 'class method', 'path': 'dom/element/stopobserving' }, +'new Ajax.PeriodicalUpdater': { 'name': 'new Ajax.PeriodicalUpdater', 'type': 'constructor', 'path': 'ajax/ajax/periodicalupdater/new' }, +'Event': { 'name': 'Event', 'type': 'class', 'path': 'dom/event' }, +'String#blank': { 'name': 'String#blank', 'type': 'instance method', 'path': 'language/string/prototype/blank' }, +'Element#on': { 'name': 'Element#on', 'type': 'instance method', 'path': 'dom/element/prototype/on' }, +'Element#positionedOffset': { 'name': 'Element#positionedOffset', 'type': 'instance method', 'path': 'dom/element/prototype/positionedoffset' }, +'Number#round': { 'name': 'Number#round', 'type': 'instance method', 'path': 'language/number/prototype/round' }, +'Array#uniq': { 'name': 'Array#uniq', 'type': 'instance method', 'path': 'language/array/prototype/uniq' }, +'Template#evaluate': { 'name': 'Template#evaluate', 'type': 'instance method', 'path': 'language/template/prototype/evaluate' }, +'Form.Element#getValue': { 'name': 'Form.Element#getValue', 'type': 'instance method', 'path': 'dom/form/element/prototype/getvalue' }, +'Event.pointerX': { 'name': 'Event.pointerX', 'type': 'class method', 'path': 'dom/event/pointerx' }, +'Element.getHeight': { 'name': 'Element.getHeight', 'type': 'class method', 'path': 'dom/element/getheight' }, +'Form.request': { 'name': 'Form.request', 'type': 'class method', 'path': 'dom/form/request' }, +'Array': { 'name': 'Array', 'type': 'class', 'path': 'language/array' }, +'Try': { 'name': 'Try', 'type': 'namespace', 'path': 'language/try' }, +'Event.pointerY': { 'name': 'Event.pointerY', 'type': 'class method', 'path': 'dom/event/pointery' }, +'Element.select': { 'name': 'Element.select', 'type': 'class method', 'path': 'dom/element/select' }, +'$A': { 'name': '$A', 'type': 'utility', 'path': 'language/dollara' }, +'Number#floor': { 'name': 'Number#floor', 'type': 'instance method', 'path': 'language/number/prototype/floor' }, +'Element#getOffsetParent': { 'name': 'Element#getOffsetParent', 'type': 'instance method', 'path': 'dom/element/prototype/getoffsetparent' }, +'ObjectRange': { 'name': 'ObjectRange', 'type': 'class', 'path': 'language/objectrange' }, +'new Element': { 'name': 'new Element', 'type': 'constructor', 'path': 'dom/element/new' }, +'String#empty': { 'name': 'String#empty', 'type': 'instance method', 'path': 'language/string/prototype/empty' }, +'Element.hasClassName': { 'name': 'Element.hasClassName', 'type': 'class method', 'path': 'dom/element/hasclassname' }, +'Element.Offset#toArray': { 'name': 'Element.Offset#toArray', 'type': 'instance method', 'path': 'dom/element/offset/prototype/toarray' }, +'Event.pointer': { 'name': 'Event.pointer', 'type': 'class method', 'path': 'dom/event/pointer' }, +'Element#setOpacity': { 'name': 'Element#setOpacity', 'type': 'instance method', 'path': 'dom/element/prototype/setopacity' }, +'Object.isHash': { 'name': 'Object.isHash', 'type': 'class method', 'path': 'language/object/ishash' }, +'Ajax.Response#request': { 'name': 'Ajax.Response#request', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/request' }, +'Event.extend': { 'name': 'Event.extend', 'type': 'class method', 'path': 'dom/event/extend' }, +'Prototype.Selector': { 'name': 'Prototype.Selector', 'type': 'namespace', 'path': 'language/prototype/selector' }, +'String.interpret': { 'name': 'String.interpret', 'type': 'class method', 'path': 'language/string/interpret' }, +'Element.viewportOffset': { 'name': 'Element.viewportOffset', 'type': 'class method', 'path': 'dom/element/viewportoffset' }, +'String#scan': { 'name': 'String#scan', 'type': 'instance method', 'path': 'language/string/prototype/scan' }, +'Event#element': { 'name': 'Event#element', 'type': 'instance method', 'path': 'dom/event/prototype/element' }, +'document.fire': { 'name': 'document.fire', 'type': 'class method', 'path': 'dom/document/fire' }, +'Object.toQueryString': { 'name': 'Object.toQueryString', 'type': 'class method', 'path': 'language/object/toquerystring' }, +'Element#hide': { 'name': 'Element#hide', 'type': 'instance method', 'path': 'dom/element/prototype/hide' }, +'$F': { 'name': '$F', 'type': 'utility', 'path': 'dom/dollarf' }, +'Hash#toQueryString': { 'name': 'Hash#toQueryString', 'type': 'instance method', 'path': 'language/hash/prototype/toquerystring' }, +'Ajax.Responders.register': { 'name': 'Ajax.Responders.register', 'type': 'class method', 'path': 'ajax/ajax/responders/register' }, +'Hash#merge': { 'name': 'Hash#merge', 'type': 'instance method', 'path': 'language/hash/prototype/merge' }, +'Enumerable#grep': { 'name': 'Enumerable#grep', 'type': 'instance method', 'path': 'language/enumerable/prototype/grep' }, +'RegExp#match': { 'name': 'RegExp#match', 'type': 'instance method', 'path': 'language/regexp/prototype/match' }, +'Object.toHTML': { 'name': 'Object.toHTML', 'type': 'class method', 'path': 'language/object/tohtml' }, +'Element.recursivelyCollect': { 'name': 'Element.recursivelyCollect', 'type': 'class method', 'path': 'dom/element/recursivelycollect' }, +'Element.adjacent': { 'name': 'Element.adjacent', 'type': 'class method', 'path': 'dom/element/adjacent' }, +'Element.next': { 'name': 'Element.next', 'type': 'class method', 'path': 'dom/element/next' }, +'$H': { 'name': '$H', 'type': 'utility', 'path': 'language/dollarh' }, +'Element#getHeight': { 'name': 'Element#getHeight', 'type': 'instance method', 'path': 'dom/element/prototype/getheight' }, +'Element#recursivelyCollect': { 'name': 'Element#recursivelyCollect', 'type': 'instance method', 'path': 'dom/element/prototype/recursivelycollect' }, +'String#toQueryParams': { 'name': 'String#toQueryParams', 'type': 'instance method', 'path': 'language/string/prototype/toqueryparams' }, +'Element.getStorage': { 'name': 'Element.getStorage', 'type': 'class method', 'path': 'dom/element/getstorage' }, +'Element.insert': { 'name': 'Element.insert', 'type': 'class method', 'path': 'dom/element/insert' }, +'new Element.Layout': { 'name': 'new Element.Layout', 'type': 'constructor', 'path': 'dom/element/layout/new' }, +'Enumerable#invoke': { 'name': 'Enumerable#invoke', 'type': 'instance method', 'path': 'language/enumerable/prototype/invoke' }, +'Element.addMethods': { 'name': 'Element.addMethods', 'type': 'class method', 'path': 'dom/element/addmethods' }, +'Element#setStyle': { 'name': 'Element#setStyle', 'type': 'instance method', 'path': 'dom/element/prototype/setstyle' }, +'Array#last': { 'name': 'Array#last', 'type': 'instance method', 'path': 'language/array/prototype/last' }, +'Element#show': { 'name': 'Element#show', 'type': 'instance method', 'path': 'dom/element/prototype/show' }, +'Event.Handler': { 'name': 'Event.Handler', 'type': 'class', 'path': 'dom/event/handler' }, +'Function#bind': { 'name': 'Function#bind', 'type': 'instance method', 'path': 'language/function/prototype/bind' }, +'Element.observe': { 'name': 'Element.observe', 'type': 'class method', 'path': 'dom/element/observe' }, +'document.viewport.getScrollOffsets': { 'name': 'document.viewport.getScrollOffsets', 'type': 'class method', 'path': 'dom/document/viewport/getscrolloffsets' }, +'String#unfilterJSON': { 'name': 'String#unfilterJSON', 'type': 'instance method', 'path': 'language/string/prototype/unfilterjson' }, +'Hash#index': { 'name': 'Hash#index', 'type': 'instance method', 'path': 'language/hash/prototype/index' }, +'Array#clear': { 'name': 'Array#clear', 'type': 'instance method', 'path': 'language/array/prototype/clear' }, +'Form.Element.getValue': { 'name': 'Form.Element.getValue', 'type': 'class method', 'path': 'dom/form/element/getvalue' }, +'Element.absolutize': { 'name': 'Element.absolutize', 'type': 'class method', 'path': 'dom/element/absolutize' }, +'Array.from': { 'name': 'Array.from', 'type': 'class method', 'path': 'language/array/from' }, +'Element.update': { 'name': 'Element.update', 'type': 'class method', 'path': 'dom/element/update' }, +'Ajax.Response#responseXML': { 'name': 'Ajax.Response#responseXML', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsexml' }, +'Form.Element#serialize': { 'name': 'Form.Element#serialize', 'type': 'instance method', 'path': 'dom/form/element/prototype/serialize' }, +'$R': { 'name': '$R', 'type': 'utility', 'path': 'language/dollarr' }, +'Form.Element.present': { 'name': 'Form.Element.present', 'type': 'class method', 'path': 'dom/form/element/present' }, +'Element.clone': { 'name': 'Element.clone', 'type': 'class method', 'path': 'dom/element/clone' }, +'Element#writeAttribute': { 'name': 'Element#writeAttribute', 'type': 'instance method', 'path': 'dom/element/prototype/writeattribute' }, +'Enumerable#inject': { 'name': 'Enumerable#inject', 'type': 'instance method', 'path': 'language/enumerable/prototype/inject' }, +'Element.visible': { 'name': 'Element.visible', 'type': 'class method', 'path': 'dom/element/visible' }, +'Element#next': { 'name': 'Element#next', 'type': 'instance method', 'path': 'dom/element/prototype/next' }, +'Element#previous': { 'name': 'Element#previous', 'type': 'instance method', 'path': 'dom/element/prototype/previous' }, +'Element': { 'name': 'Element', 'type': 'class', 'path': 'dom/element' }, +'Element.Layout.COMPOSITE_PROPERTIES': { 'name': 'Element.Layout.COMPOSITE_PROPERTIES', 'type': 'constant', 'path': 'dom/element/layout/composite_properties' }, +'new Selector': { 'name': 'new Selector', 'type': 'constructor', 'path': 'dom/selector/new' }, +'Element#descendants': { 'name': 'Element#descendants', 'type': 'instance method', 'path': 'dom/element/prototype/descendants' }, +'Object': { 'name': 'Object', 'type': 'class', 'path': 'language/object' }, +'Enumerable#include': { 'name': 'Enumerable#include', 'type': 'instance method', 'path': 'language/enumerable/prototype/include' }, +'String#dasherize': { 'name': 'String#dasherize', 'type': 'instance method', 'path': 'language/string/prototype/dasherize' }, +'Element#replace': { 'name': 'Element#replace', 'type': 'instance method', 'path': 'dom/element/prototype/replace' }, +'Element#toggle': { 'name': 'Element#toggle', 'type': 'instance method', 'path': 'dom/element/prototype/toggle' }, +'String#interpolate': { 'name': 'String#interpolate', 'type': 'instance method', 'path': 'language/string/prototype/interpolate' }, +'String#camelize': { 'name': 'String#camelize', 'type': 'instance method', 'path': 'language/string/prototype/camelize' }, +'new ObjectRange': { 'name': 'new ObjectRange', 'type': 'constructor', 'path': 'language/objectrange/new' }, +'Object.isElement': { 'name': 'Object.isElement', 'type': 'class method', 'path': 'language/object/iselement' }, +'Element#relativize': { 'name': 'Element#relativize', 'type': 'instance method', 'path': 'dom/element/prototype/relativize' }, +'String#unescapeHTML': { 'name': 'String#unescapeHTML', 'type': 'instance method', 'path': 'language/string/prototype/unescapehtml' }, +'Array#flatten': { 'name': 'Array#flatten', 'type': 'instance method', 'path': 'language/array/prototype/flatten' }, +'Prototype.BrowserFeatures.SelectorsAPI': { 'name': 'Prototype.BrowserFeatures.SelectorsAPI', 'type': 'class property', 'path': 'language/prototype/browserfeatures/selectorsapi' }, +'Element.makePositioned': { 'name': 'Element.makePositioned', 'type': 'class method', 'path': 'dom/element/makepositioned' }, +'Event#isMiddleClick': { 'name': 'Event#isMiddleClick', 'type': 'instance method', 'path': 'dom/event/prototype/ismiddleclick' }, +'document': { 'name': 'document', 'type': 'namespace', 'path': 'dom/document' }, +'String#times': { 'name': 'String#times', 'type': 'instance method', 'path': 'language/string/prototype/times' }, +'Abstract.EventObserver': { 'name': 'Abstract.EventObserver', 'type': 'class', 'path': 'dom/abstract/eventobserver' }, +'Event.findElement': { 'name': 'Event.findElement', 'type': 'class method', 'path': 'dom/event/findelement' }, +'Element.positionedOffset': { 'name': 'Element.positionedOffset', 'type': 'class method', 'path': 'dom/element/positionedoffset' }, +'Form#reset': { 'name': 'Form#reset', 'type': 'instance method', 'path': 'dom/form/prototype/reset' }, +'$': { 'name': '$', 'type': 'utility', 'path': 'dom/dollar' }, +'Abstract.TimedObserver': { 'name': 'Abstract.TimedObserver', 'type': 'class', 'path': 'dom/abstract/timedobserver' }, +'Hash#get': { 'name': 'Hash#get', 'type': 'instance method', 'path': 'language/hash/prototype/get' }, +'Number': { 'name': 'Number', 'type': 'class', 'path': 'language/number' }, +'Element.firstDescendant': { 'name': 'Element.firstDescendant', 'type': 'class method', 'path': 'dom/element/firstdescendant' }, +'document.viewport.getDimensions': { 'name': 'document.viewport.getDimensions', 'type': 'class method', 'path': 'dom/document/viewport/getdimensions' }, +'Ajax.Response#statusText': { 'name': 'Ajax.Response#statusText', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/statustext' }, +'Element.remove': { 'name': 'Element.remove', 'type': 'class method', 'path': 'dom/element/remove' }, +'Element.setStyle': { 'name': 'Element.setStyle', 'type': 'class method', 'path': 'dom/element/setstyle' }, +'new Form.Observer': { 'name': 'new Form.Observer', 'type': 'constructor', 'path': 'dom/form/observer/new' }, +'Element.up': { 'name': 'Element.up', 'type': 'class method', 'path': 'dom/element/up' }, +'Element.hide': { 'name': 'Element.hide', 'type': 'class method', 'path': 'dom/element/hide' }, +'Function': { 'name': 'Function', 'type': 'class', 'path': 'language/function' }, +'Event.isMiddleClick': { 'name': 'Event.isMiddleClick', 'type': 'class method', 'path': 'dom/event/ismiddleclick' }, +'Event.Handler#stop': { 'name': 'Event.Handler#stop', 'type': 'instance property', 'path': 'dom/event/handler/prototype/stop' }, +'Number#ceil': { 'name': 'Number#ceil', 'type': 'instance method', 'path': 'language/number/prototype/ceil' }, +'Form.Element#setValue': { 'name': 'Form.Element#setValue', 'type': 'instance method', 'path': 'dom/form/element/prototype/setvalue' }, +'Element.getStyle': { 'name': 'Element.getStyle', 'type': 'class method', 'path': 'dom/element/getstyle' }, +'Element#down': { 'name': 'Element#down', 'type': 'instance method', 'path': 'dom/element/prototype/down' }, +'Element.show': { 'name': 'Element.show', 'type': 'class method', 'path': 'dom/element/show' }, +'Element.Layout#toCSS': { 'name': 'Element.Layout#toCSS', 'type': 'instance method', 'path': 'dom/element/layout/prototype/tocss' }, +'ObjectRange#end': { 'name': 'ObjectRange#end', 'type': 'instance property', 'path': 'language/objectrange/prototype/end' }, +'Element#cumulativeScrollOffset': { 'name': 'Element#cumulativeScrollOffset', 'type': 'instance method', 'path': 'dom/element/prototype/cumulativescrolloffset' }, +'Form.getElements': { 'name': 'Form.getElements', 'type': 'class method', 'path': 'dom/form/getelements' }, +'Element.writeAttribute': { 'name': 'Element.writeAttribute', 'type': 'class method', 'path': 'dom/element/writeattribute' }, +'Element.cleanWhitespace': { 'name': 'Element.cleanWhitespace', 'type': 'class method', 'path': 'dom/element/cleanwhitespace' }, +'Form#request': { 'name': 'Form#request', 'type': 'instance method', 'path': 'dom/form/prototype/request' }, +'Date': { 'name': 'Date', 'type': 'class', 'path': 'language/date' }, +'Array#clone': { 'name': 'Array#clone', 'type': 'instance method', 'path': 'language/array/prototype/clone' }, +'Element.inspect': { 'name': 'Element.inspect', 'type': 'class method', 'path': 'dom/element/inspect' }, +'Ajax.Response#getAllResponseHeaders': { 'name': 'Ajax.Response#getAllResponseHeaders', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getallresponseheaders' }, +'Event#isLeftClick': { 'name': 'Event#isLeftClick', 'type': 'instance method', 'path': 'dom/event/prototype/isleftclick' }, +'Element.previous': { 'name': 'Element.previous', 'type': 'class method', 'path': 'dom/element/previous' }, +'Element#descendantOf': { 'name': 'Element#descendantOf', 'type': 'instance method', 'path': 'dom/element/prototype/descendantof' }, +'Selector#findElements': { 'name': 'Selector#findElements', 'type': 'instance method', 'path': 'dom/selector/prototype/findelements' }, +'Element#getWidth': { 'name': 'Element#getWidth', 'type': 'instance method', 'path': 'dom/element/prototype/getwidth' }, +'Element#getLayout': { 'name': 'Element#getLayout', 'type': 'instance method', 'path': 'dom/element/prototype/getlayout' }, +'new PeriodicalExecuter': { 'name': 'new PeriodicalExecuter', 'type': 'constructor', 'path': 'language/periodicalexecuter/new' }, +'Template': { 'name': 'Template', 'type': 'class', 'path': 'language/template' }, +'String#capitalize': { 'name': 'String#capitalize', 'type': 'instance method', 'path': 'language/string/prototype/capitalize' }, +'Element#getElementsBySelector': { 'name': 'Element#getElementsBySelector', 'type': 'instance method', 'path': 'dom/element/prototype/getelementsbyselector' }, +'Enumerable#select': { 'name': 'Enumerable#select', 'type': 'instance method', 'path': 'language/enumerable/prototype/select' }, +'Event#pointer': { 'name': 'Event#pointer', 'type': 'instance method', 'path': 'dom/event/prototype/pointer' }, +'Prototype': { 'name': 'Prototype', 'type': 'namespace', 'path': 'language/prototype' }, +'RegExp.escape': { 'name': 'RegExp.escape', 'type': 'class method', 'path': 'language/regexp/escape' }, +'Hash#clone': { 'name': 'Hash#clone', 'type': 'instance method', 'path': 'language/hash/prototype/clone' }, +'Element#cumulativeOffset': { 'name': 'Element#cumulativeOffset', 'type': 'instance method', 'path': 'dom/element/prototype/cumulativeoffset' }, +'Element#getOpacity': { 'name': 'Element#getOpacity', 'type': 'instance method', 'path': 'dom/element/prototype/getopacity' }, +'Hash#inspect': { 'name': 'Hash#inspect', 'type': 'instance method', 'path': 'language/hash/prototype/inspect' }, +'Event.fire': { 'name': 'Event.fire', 'type': 'class method', 'path': 'dom/event/fire' }, +'Element.extend': { 'name': 'Element.extend', 'type': 'class method', 'path': 'dom/element/extend' }, +'Form.Element.focus': { 'name': 'Form.Element.focus', 'type': 'class method', 'path': 'dom/form/element/focus' }, +'Ajax.PeriodicalUpdater#start': { 'name': 'Ajax.PeriodicalUpdater#start', 'type': 'instance method', 'path': 'ajax/ajax/periodicalupdater/prototype/start' }, +'Element.getElementsBySelector': { 'name': 'Element.getElementsBySelector', 'type': 'class method', 'path': 'dom/element/getelementsbyselector' }, +'Element#makeClipping': { 'name': 'Element#makeClipping', 'type': 'instance method', 'path': 'dom/element/prototype/makeclipping' }, +'Element.makeClipping': { 'name': 'Element.makeClipping', 'type': 'class method', 'path': 'dom/element/makeclipping' }, +'Abstract': { 'name': 'Abstract', 'type': 'namespace', 'path': 'dom/abstract' }, +'Element.addClassName': { 'name': 'Element.addClassName', 'type': 'class method', 'path': 'dom/element/addclassname' }, +'Element.removeClassName': { 'name': 'Element.removeClassName', 'type': 'class method', 'path': 'dom/element/removeclassname' }, +'Form.Element.clear': { 'name': 'Form.Element.clear', 'type': 'class method', 'path': 'dom/form/element/clear' }, +'Element.setOpacity': { 'name': 'Element.setOpacity', 'type': 'class method', 'path': 'dom/element/setopacity' }, +'String#truncate': { 'name': 'String#truncate', 'type': 'instance method', 'path': 'language/string/prototype/truncate' }, +'Form.disable': { 'name': 'Form.disable', 'type': 'class method', 'path': 'dom/form/disable' }, +'Element#hasClassName': { 'name': 'Element#hasClassName', 'type': 'instance method', 'path': 'dom/element/prototype/hasclassname' }, +'Ajax.Response#getHeader': { 'name': 'Ajax.Response#getHeader', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getheader' }, +'Element#fire': { 'name': 'Element#fire', 'type': 'instance method', 'path': 'dom/element/prototype/fire' }, +'Number#toColorPart': { 'name': 'Number#toColorPart', 'type': 'instance method', 'path': 'language/number/prototype/tocolorpart' }, +'Selector.findChildElements': { 'name': 'Selector.findChildElements', 'type': 'class method', 'path': 'dom/selector/findchildelements' }, +'Element#firstDescendant': { 'name': 'Element#firstDescendant', 'type': 'instance method', 'path': 'dom/element/prototype/firstdescendant' }, +'Form.Element.disable': { 'name': 'Form.Element.disable', 'type': 'class method', 'path': 'dom/form/element/disable' }, +'Element.Methods': { 'name': 'Element.Methods', 'type': 'mixin', 'path': 'dom/element/methods' }, +'String#evalJSON': { 'name': 'String#evalJSON', 'type': 'instance method', 'path': 'language/string/prototype/evaljson' }, +'String#succ': { 'name': 'String#succ', 'type': 'instance method', 'path': 'language/string/prototype/succ' }, +'Form.Element.setValue': { 'name': 'Form.Element.setValue', 'type': 'class method', 'path': 'dom/form/element/setvalue' }, +'Ajax.Request#success': { 'name': 'Ajax.Request#success', 'type': 'instance method', 'path': 'ajax/ajax/request/prototype/success' }, +'Ajax.PeriodicalUpdater#stop': { 'name': 'Ajax.PeriodicalUpdater#stop', 'type': 'instance method', 'path': 'ajax/ajax/periodicalupdater/prototype/stop' }, +'Element#select': { 'name': 'Element#select', 'type': 'instance method', 'path': 'dom/element/prototype/select' }, +'PeriodicalExecuter': { 'name': 'PeriodicalExecuter', 'type': 'class', 'path': 'language/periodicalexecuter' }, +'Prototype.BrowserFeatures.XPath': { 'name': 'Prototype.BrowserFeatures.XPath', 'type': 'class property', 'path': 'language/prototype/browserfeatures/xpath' }, +'Element#removeClassName': { 'name': 'Element#removeClassName', 'type': 'instance method', 'path': 'dom/element/prototype/removeclassname' }, +'Element#getDimensions': { 'name': 'Element#getDimensions', 'type': 'instance method', 'path': 'dom/element/prototype/getdimensions' }, +'Element#observe': { 'name': 'Element#observe', 'type': 'instance method', 'path': 'dom/element/prototype/observe' }, +'Element#up': { 'name': 'Element#up', 'type': 'instance method', 'path': 'dom/element/prototype/up' }, +'Ajax.Updater': { 'name': 'Ajax.Updater', 'type': 'class', 'path': 'ajax/ajax/updater' }, +'Prototype.Version': { 'name': 'Prototype.Version', 'type': 'class property', 'path': 'language/prototype/version' }, +'String#underscore': { 'name': 'String#underscore', 'type': 'instance method', 'path': 'language/string/prototype/underscore' }, +'String#evalScripts': { 'name': 'String#evalScripts', 'type': 'instance method', 'path': 'language/string/prototype/evalscripts' }, +'Array#indexOf': { 'name': 'Array#indexOf', 'type': 'instance method', 'path': 'language/array/prototype/indexof' }, +'Event.isRightClick': { 'name': 'Event.isRightClick', 'type': 'class method', 'path': 'dom/event/isrightclick' }, +'Form#findFirstElement': { 'name': 'Form#findFirstElement', 'type': 'instance method', 'path': 'dom/form/prototype/findfirstelement' }, +'Element#clone': { 'name': 'Element#clone', 'type': 'instance method', 'path': 'dom/element/prototype/clone' }, +'$w': { 'name': '$w', 'type': 'utility', 'path': 'language/dollarw' }, +'Class': { 'name': 'Class', 'type': 'class', 'path': 'language/class' }, +'Event.stopObserving': { 'name': 'Event.stopObserving', 'type': 'class method', 'path': 'dom/event/stopobserving' }, +'Form.enable': { 'name': 'Form.enable', 'type': 'class method', 'path': 'dom/form/enable' }, +'Array#first': { 'name': 'Array#first', 'type': 'instance method', 'path': 'language/array/prototype/first' }, +'Element.relativize': { 'name': 'Element.relativize', 'type': 'class method', 'path': 'dom/element/relativize' }, +'Enumerable#toArray': { 'name': 'Enumerable#toArray', 'type': 'instance method', 'path': 'language/enumerable/prototype/toarray' }, +'Hash#unset': { 'name': 'Hash#unset', 'type': 'instance method', 'path': 'language/hash/prototype/unset' }, +'Form.getInputs': { 'name': 'Form.getInputs', 'type': 'class method', 'path': 'dom/form/getinputs' }, +'Element#undoPositioned': { 'name': 'Element#undoPositioned', 'type': 'instance method', 'path': 'dom/element/prototype/undopositioned' }, +'Element#cleanWhitespace': { 'name': 'Element#cleanWhitespace', 'type': 'instance method', 'path': 'dom/element/prototype/cleanwhitespace' }, +'Prototype.Browser': { 'name': 'Prototype.Browser', 'type': 'namespace', 'path': 'language/prototype/browser' }, +'String#startsWith': { 'name': 'String#startsWith', 'type': 'instance method', 'path': 'language/string/prototype/startswith' }, +'Form.Element#present': { 'name': 'Form.Element#present', 'type': 'instance method', 'path': 'dom/form/element/prototype/present' }, +'Form.Element': { 'name': 'Form.Element', 'type': 'namespace', 'path': 'dom/form/element' }, +'Element.ancestors': { 'name': 'Element.ancestors', 'type': 'class method', 'path': 'dom/element/ancestors' }, +'Array#compact': { 'name': 'Array#compact', 'type': 'instance method', 'path': 'language/array/prototype/compact' }, +'String#endsWith': { 'name': 'String#endsWith', 'type': 'instance method', 'path': 'language/string/prototype/endswith' }, +'Element.classNames': { 'name': 'Element.classNames', 'type': 'class method', 'path': 'dom/element/classnames' }, +'Element#visible': { 'name': 'Element#visible', 'type': 'instance method', 'path': 'dom/element/prototype/visible' }, +'Class.create': { 'name': 'Class.create', 'type': 'class method', 'path': 'language/class/create' }, +'Element.down': { 'name': 'Element.down', 'type': 'class method', 'path': 'dom/element/down' }, +'Number#abs': { 'name': 'Number#abs', 'type': 'instance method', 'path': 'language/number/prototype/abs' }, +'String#include': { 'name': 'String#include', 'type': 'instance method', 'path': 'language/string/prototype/include' }, +'Enumerable#any': { 'name': 'Enumerable#any', 'type': 'instance method', 'path': 'language/enumerable/prototype/any' }, +'Element.toggle': { 'name': 'Element.toggle', 'type': 'class method', 'path': 'dom/element/toggle' }, +'Prototype.Selector.select': { 'name': 'Prototype.Selector.select', 'type': 'class method', 'path': 'language/prototype/selector/select' }, +'Enumerable#pluck': { 'name': 'Enumerable#pluck', 'type': 'instance method', 'path': 'language/enumerable/prototype/pluck' }, +'Form.Element.EventObserver': { 'name': 'Form.Element.EventObserver', 'type': 'class', 'path': 'dom/form/element/eventobserver' }, +'Element.getDimensions': { 'name': 'Element.getDimensions', 'type': 'class method', 'path': 'dom/element/getdimensions' }, +'Enumerable#collect': { 'name': 'Enumerable#collect', 'type': 'instance method', 'path': 'language/enumerable/prototype/collect' }, +'Form.Element.Observer': { 'name': 'Form.Element.Observer', 'type': 'class', 'path': 'dom/form/element/observer' }, +'String#gsub': { 'name': 'String#gsub', 'type': 'instance method', 'path': 'language/string/prototype/gsub' }, +'RegExp': { 'name': 'RegExp', 'type': 'class', 'path': 'language/regexp' }, +'Element#wrap': { 'name': 'Element#wrap', 'type': 'instance method', 'path': 'dom/element/prototype/wrap' }, +'Event.on': { 'name': 'Event.on', 'type': 'class method', 'path': 'dom/event/on' }, +'Ajax.Request': { 'name': 'Ajax.Request', 'type': 'class', 'path': 'ajax/ajax/request' }, +'Enumerable#inspect': { 'name': 'Enumerable#inspect', 'type': 'instance method', 'path': 'language/enumerable/prototype/inspect' }, +'Form.Element#enable': { 'name': 'Form.Element#enable', 'type': 'instance method', 'path': 'dom/form/element/prototype/enable' }, +'Object.isNumber': { 'name': 'Object.isNumber', 'type': 'class method', 'path': 'language/object/isnumber' }, +'document.stopObserving': { 'name': 'document.stopObserving', 'type': 'class method', 'path': 'dom/document/stopobserving' }, +'Element.Layout': { 'name': 'Element.Layout', 'type': 'class', 'path': 'dom/element/layout' }, +'String#strip': { 'name': 'String#strip', 'type': 'instance method', 'path': 'language/string/prototype/strip' }, +'new Element.Offset': { 'name': 'new Element.Offset', 'type': 'constructor', 'path': 'dom/element/offset/new' }, +'Element.toggleClassName': { 'name': 'Element.toggleClassName', 'type': 'class method', 'path': 'dom/element/toggleclassname' }, +'Event#findElement': { 'name': 'Event#findElement', 'type': 'instance method', 'path': 'dom/event/prototype/findelement' }, +'Element.match': { 'name': 'Element.match', 'type': 'class method', 'path': 'dom/element/match' }, +'Event#stop': { 'name': 'Event#stop', 'type': 'instance method', 'path': 'dom/event/prototype/stop' }, +'Form.serialize': { 'name': 'Form.serialize', 'type': 'class method', 'path': 'dom/form/serialize' }, +'Object.clone': { 'name': 'Object.clone', 'type': 'class method', 'path': 'language/object/clone' }, +'Object.isString': { 'name': 'Object.isString', 'type': 'class method', 'path': 'language/object/isstring' }, +'Enumerable#entries': { 'name': 'Enumerable#entries', 'type': 'instance method', 'path': 'language/enumerable/prototype/entries' }, +'Element#siblings': { 'name': 'Element#siblings', 'type': 'instance method', 'path': 'dom/element/prototype/siblings' }, +'Enumerable#member': { 'name': 'Enumerable#member', 'type': 'instance method', 'path': 'language/enumerable/prototype/member' }, +'Element.readAttribute': { 'name': 'Element.readAttribute', 'type': 'class method', 'path': 'dom/element/readattribute' }, +'Ajax.Responders.unregister': { 'name': 'Ajax.Responders.unregister', 'type': 'class method', 'path': 'ajax/ajax/responders/unregister' }, +'Element#addClassName': { 'name': 'Element#addClassName', 'type': 'instance method', 'path': 'dom/element/prototype/addclassname' }, +'String#stripScripts': { 'name': 'String#stripScripts', 'type': 'instance method', 'path': 'language/string/prototype/stripscripts' }, +'Enumerable': { 'name': 'Enumerable', 'type': 'mixin', 'path': 'language/enumerable' }, +'Element.Layout.PROPERTIES': { 'name': 'Element.Layout.PROPERTIES', 'type': 'constant', 'path': 'dom/element/layout/properties' }, +'Selector': { 'name': 'Selector', 'type': 'class', 'path': 'dom/selector' }, +'Enumerable#detect': { 'name': 'Enumerable#detect', 'type': 'instance method', 'path': 'language/enumerable/prototype/detect' }, +'Form.findFirstElement': { 'name': 'Form.findFirstElement', 'type': 'class method', 'path': 'dom/form/findfirstelement' }, +'Ajax section': { 'name': 'Ajax section', 'type': 'section', 'path': 'ajax' }, +'new Event.Handler': { 'name': 'new Event.Handler', 'type': 'constructor', 'path': 'dom/event/handler/new' }, +'Enumerable#every': { 'name': 'Enumerable#every', 'type': 'instance method', 'path': 'language/enumerable/prototype/every' }, +'Prototype.Selector.match': { 'name': 'Prototype.Selector.match', 'type': 'class method', 'path': 'language/prototype/selector/match' }, +'Enumerable#all': { 'name': 'Enumerable#all', 'type': 'instance method', 'path': 'language/enumerable/prototype/all' }, +'Element.store': { 'name': 'Element.store', 'type': 'class method', 'path': 'dom/element/store' }, +'Language section': { 'name': 'Language section', 'type': 'section', 'path': 'language' }, +'String#sub': { 'name': 'String#sub', 'type': 'instance method', 'path': 'language/string/prototype/sub' }, +'Element.Layout#get': { 'name': 'Element.Layout#get', 'type': 'instance method', 'path': 'dom/element/layout/prototype/get' }, +'Element.getWidth': { 'name': 'Element.getWidth', 'type': 'class method', 'path': 'dom/element/getwidth' }, +'Enumerable#sortBy': { 'name': 'Enumerable#sortBy', 'type': 'instance method', 'path': 'language/enumerable/prototype/sortby' }, +'Element.measure': { 'name': 'Element.measure', 'type': 'class method', 'path': 'dom/element/measure' }, +'Function#delay': { 'name': 'Function#delay', 'type': 'instance method', 'path': 'language/function/prototype/delay' }, +'Element.cumulativeScrollOffset': { 'name': 'Element.cumulativeScrollOffset', 'type': 'class method', 'path': 'dom/element/cumulativescrolloffset' }, +'Element.cumulativeOffset': { 'name': 'Element.cumulativeOffset', 'type': 'class method', 'path': 'dom/element/cumulativeoffset' }, +'Event.observe': { 'name': 'Event.observe', 'type': 'class method', 'path': 'dom/event/observe' }, +'Ajax.Responders': { 'name': 'Ajax.Responders', 'type': 'namespace', 'path': 'ajax/ajax/responders' }, +'Enumerable#find': { 'name': 'Enumerable#find', 'type': 'instance method', 'path': 'language/enumerable/prototype/find' }, +'Array#inspect': { 'name': 'Array#inspect', 'type': 'instance method', 'path': 'language/array/prototype/inspect' }, +'Enumerable#map': { 'name': 'Enumerable#map', 'type': 'instance method', 'path': 'language/enumerable/prototype/map' }, +'Element.fire': { 'name': 'Element.fire', 'type': 'class method', 'path': 'dom/element/fire' }, +'Element.getOpacity': { 'name': 'Element.getOpacity', 'type': 'class method', 'path': 'dom/element/getopacity' }, +'Form#getElements': { 'name': 'Form#getElements', 'type': 'instance method', 'path': 'dom/form/prototype/getelements' }, +'Form#serialize': { 'name': 'Form#serialize', 'type': 'instance method', 'path': 'dom/form/prototype/serialize' }, +'Element.undoPositioned': { 'name': 'Element.undoPositioned', 'type': 'class method', 'path': 'dom/element/undopositioned' }, +'Element#inspect': { 'name': 'Element#inspect', 'type': 'instance method', 'path': 'dom/element/prototype/inspect' }, +'Form.EventObserver': { 'name': 'Form.EventObserver', 'type': 'class', 'path': 'dom/form/eventobserver' }, +'Element#retrieve': { 'name': 'Element#retrieve', 'type': 'instance method', 'path': 'dom/element/prototype/retrieve' }, +'Element.empty': { 'name': 'Element.empty', 'type': 'class method', 'path': 'dom/element/empty' }, +'Element.Offset': { 'name': 'Element.Offset', 'type': 'class', 'path': 'dom/element/offset' }, +'Element.nextSiblings': { 'name': 'Element.nextSiblings', 'type': 'class method', 'path': 'dom/element/nextsiblings' }, +'Prototype.K': { 'name': 'Prototype.K', 'type': 'class method', 'path': 'language/prototype/k' }, +'String#escapeHTML': { 'name': 'String#escapeHTML', 'type': 'instance method', 'path': 'language/string/prototype/escapehtml' }, +'Object.values': { 'name': 'Object.values', 'type': 'class method', 'path': 'language/object/values' }, +'Enumerable#max': { 'name': 'Enumerable#max', 'type': 'instance method', 'path': 'language/enumerable/prototype/max' }, +'Ajax.PeriodicalUpdater': { 'name': 'Ajax.PeriodicalUpdater', 'type': 'class', 'path': 'ajax/ajax/periodicalupdater' }, +'Form.serializeElements': { 'name': 'Form.serializeElements', 'type': 'class method', 'path': 'dom/form/serializeelements' }, +'Hash#set': { 'name': 'Hash#set', 'type': 'instance method', 'path': 'language/hash/prototype/set' }, +'Date#toJSON': { 'name': 'Date#toJSON', 'type': 'instance method', 'path': 'language/date/prototype/tojson' }, +'Form.Element#clear': { 'name': 'Form.Element#clear', 'type': 'instance method', 'path': 'dom/form/element/prototype/clear' }, +'Element.Offset#relativeTo': { 'name': 'Element.Offset#relativeTo', 'type': 'instance method', 'path': 'dom/element/offset/prototype/relativeto' }, +'Array#without': { 'name': 'Array#without', 'type': 'instance method', 'path': 'language/array/prototype/without' }, +'Form.Observer': { 'name': 'Form.Observer', 'type': 'class', 'path': 'dom/form/observer' }, +'Hash': { 'name': 'Hash', 'type': 'class', 'path': 'language/hash' }, +'new Form.Element.Observer': { 'name': 'new Form.Element.Observer', 'type': 'constructor', 'path': 'dom/form/element/observer/new' }, +'Element#toggleClassName': { 'name': 'Element#toggleClassName', 'type': 'instance method', 'path': 'dom/element/prototype/toggleclassname' }, +'Selector.findElement': { 'name': 'Selector.findElement', 'type': 'class method', 'path': 'dom/selector/findelement' }, +'Array#reverse': { 'name': 'Array#reverse', 'type': 'instance method', 'path': 'language/array/prototype/reverse' }, +'new Hash': { 'name': 'new Hash', 'type': 'constructor', 'path': 'language/hash/new' }, +'Enumerable#eachSlice': { 'name': 'Enumerable#eachSlice', 'type': 'instance method', 'path': 'language/enumerable/prototype/eachslice' }, +'Element.siblings': { 'name': 'Element.siblings', 'type': 'class method', 'path': 'dom/element/siblings' }, +'ObjectRange#include': { 'name': 'ObjectRange#include', 'type': 'instance method', 'path': 'language/objectrange/prototype/include' }, +'Number#toPaddedString': { 'name': 'Number#toPaddedString', 'type': 'instance method', 'path': 'language/number/prototype/topaddedstring' }, +'Hash#each': { 'name': 'Hash#each', 'type': 'instance method', 'path': 'language/hash/prototype/each' }, +'Form#getInputs': { 'name': 'Form#getInputs', 'type': 'instance method', 'path': 'dom/form/prototype/getinputs' }, +'Element.wrap': { 'name': 'Element.wrap', 'type': 'class method', 'path': 'dom/element/wrap' }, +'Form#disable': { 'name': 'Form#disable', 'type': 'instance method', 'path': 'dom/form/prototype/disable' }, +'Hash#values': { 'name': 'Hash#values', 'type': 'instance method', 'path': 'language/hash/prototype/values' }, +'Element#viewportOffset': { 'name': 'Element#viewportOffset', 'type': 'instance method', 'path': 'dom/element/prototype/viewportoffset' }, +'Element#ancestors': { 'name': 'Element#ancestors', 'type': 'instance method', 'path': 'dom/element/prototype/ancestors' }, +'ObjectRange#start': { 'name': 'ObjectRange#start', 'type': 'instance property', 'path': 'language/objectrange/prototype/start' }, +'Element.immediateDescendants': { 'name': 'Element.immediateDescendants', 'type': 'class method', 'path': 'dom/element/immediatedescendants' }, +'Form.Element#disable': { 'name': 'Form.Element#disable', 'type': 'instance method', 'path': 'dom/form/element/prototype/disable' }, +'Hash#toObject': { 'name': 'Hash#toObject', 'type': 'instance method', 'path': 'language/hash/prototype/toobject' }, +'Event.stop': { 'name': 'Event.stop', 'type': 'class method', 'path': 'dom/event/stop' }, +'Ajax.Request#getHeader': { 'name': 'Ajax.Request#getHeader', 'type': 'instance method', 'path': 'ajax/ajax/request/prototype/getheader' }, +'Element#scrollTo': { 'name': 'Element#scrollTo', 'type': 'instance method', 'path': 'dom/element/prototype/scrollto' }, +'Form': { 'name': 'Form', 'type': 'namespace', 'path': 'dom/form' }, +'String#isJSON': { 'name': 'String#isJSON', 'type': 'instance method', 'path': 'language/string/prototype/isjson' }, +'Element#childElements': { 'name': 'Element#childElements', 'type': 'instance method', 'path': 'dom/element/prototype/childelements' }, +'Element#getStorage': { 'name': 'Element#getStorage', 'type': 'instance method', 'path': 'dom/element/prototype/getstorage' }, +'Element.Offset#toString': { 'name': 'Element.Offset#toString', 'type': 'instance method', 'path': 'dom/element/offset/prototype/tostring' }, +'Event#extend': { 'name': 'Event#extend', 'type': 'instance method', 'path': 'dom/event/prototype/extend' }, +'Event.element': { 'name': 'Event.element', 'type': 'class method', 'path': 'dom/event/element' }, +'new Abstract.TimedObserver': { 'name': 'new Abstract.TimedObserver', 'type': 'constructor', 'path': 'dom/abstract/timedobserver/new' }, +'Object.isUndefined': { 'name': 'Object.isUndefined', 'type': 'class method', 'path': 'language/object/isundefined' }, +'Function#argumentNames': { 'name': 'Function#argumentNames', 'type': 'instance method', 'path': 'language/function/prototype/argumentnames' }, +'Ajax.Response#transport': { 'name': 'Ajax.Response#transport', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/transport' }, +'Prototype.Selector.find': { 'name': 'Prototype.Selector.find', 'type': 'class method', 'path': 'language/prototype/selector/find' }, +'Ajax.activeRequestCount': { 'name': 'Ajax.activeRequestCount', 'type': 'class property', 'path': 'ajax/ajax/activerequestcount' }, +'Ajax.Response#getResponseHeader': { 'name': 'Ajax.Response#getResponseHeader', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getresponseheader' }, +'String#toArray': { 'name': 'String#toArray', 'type': 'instance method', 'path': 'language/string/prototype/toarray' }, +'document.observe': { 'name': 'document.observe', 'type': 'class method', 'path': 'dom/document/observe' }, +'Enumerable#each': { 'name': 'Enumerable#each', 'type': 'instance method', 'path': 'language/enumerable/prototype/each' }, +'Object.keys': { 'name': 'Object.keys', 'type': 'class method', 'path': 'language/object/keys' }, +'Prototype.BrowserFeatures': { 'name': 'Prototype.BrowserFeatures', 'type': 'namespace', 'path': 'language/prototype/browserfeatures' }, +'Element#readAttribute': { 'name': 'Element#readAttribute', 'type': 'instance method', 'path': 'dom/element/prototype/readattribute' }, +'Element.retrieve': { 'name': 'Element.retrieve', 'type': 'class method', 'path': 'dom/element/retrieve' }, +'Class#addMethods': { 'name': 'Class#addMethods', 'type': 'instance method', 'path': 'language/class/prototype/addmethods' }, +'Ajax.Response#getAllHeaders': { 'name': 'Ajax.Response#getAllHeaders', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getallheaders' }, +'Enumerable#inGroupsOf': { 'name': 'Enumerable#inGroupsOf', 'type': 'instance method', 'path': 'language/enumerable/prototype/ingroupsof' }, +'Event#isRightClick': { 'name': 'Event#isRightClick', 'type': 'instance method', 'path': 'dom/event/prototype/isrightclick' }, +'Array#lastIndexOf': { 'name': 'Array#lastIndexOf', 'type': 'instance method', 'path': 'language/array/prototype/lastindexof' }, +'Function#methodize': { 'name': 'Function#methodize', 'type': 'instance method', 'path': 'language/function/prototype/methodize' }, +'$$': { 'name': '$$', 'type': 'utility', 'path': 'dom/dollardollar' }, +'Element.Offset#inspect': { 'name': 'Element.Offset#inspect', 'type': 'instance method', 'path': 'dom/element/offset/prototype/inspect' }, +'Element#absolutize': { 'name': 'Element#absolutize', 'type': 'instance method', 'path': 'dom/element/prototype/absolutize' }, +'Object.isFunction': { 'name': 'Object.isFunction', 'type': 'class method', 'path': 'language/object/isfunction' }, +'Element.undoClipping': { 'name': 'Element.undoClipping', 'type': 'class method', 'path': 'dom/element/undoclipping' }, +'Element.childElements': { 'name': 'Element.childElements', 'type': 'class method', 'path': 'dom/element/childelements' }, +'Form.Element.select': { 'name': 'Form.Element.select', 'type': 'class method', 'path': 'dom/form/element/select' }, +'Ajax': { 'name': 'Ajax', 'type': 'namespace', 'path': 'ajax/ajax' }, +'Element#undoClipping': { 'name': 'Element#undoClipping', 'type': 'instance method', 'path': 'dom/element/prototype/undoclipping' }, +'Element#match': { 'name': 'Element#match', 'type': 'instance method', 'path': 'dom/element/prototype/match' }, +'Form.Element.enable': { 'name': 'Form.Element.enable', 'type': 'class method', 'path': 'dom/form/element/enable' }, +'Enumerable#min': { 'name': 'Enumerable#min', 'type': 'instance method', 'path': 'language/enumerable/prototype/min' }, +'String#stripTags': { 'name': 'String#stripTags', 'type': 'instance method', 'path': 'language/string/prototype/striptags' }, +'Number#times': { 'name': 'Number#times', 'type': 'instance method', 'path': 'language/number/prototype/times' }, +'Date#toISOString': { 'name': 'Date#toISOString', 'type': 'instance method', 'path': 'language/date/prototype/toisostring' }, +'Element.on': { 'name': 'Element.on', 'type': 'class method', 'path': 'dom/element/on' }, +'Element.scrollTo': { 'name': 'Element.scrollTo', 'type': 'class method', 'path': 'dom/element/scrollto' }, +'Event.isLeftClick': { 'name': 'Event.isLeftClick', 'type': 'class method', 'path': 'dom/event/isleftclick' }, +'Element#identify': { 'name': 'Element#identify', 'type': 'instance method', 'path': 'dom/element/prototype/identify' }, +'document.viewport': { 'name': 'document.viewport', 'type': 'namespace', 'path': 'dom/document/viewport' }, +'Array#toArray': { 'name': 'Array#toArray', 'type': 'instance method', 'path': 'language/array/prototype/toarray' }, +'Element#clonePosition': { 'name': 'Element#clonePosition', 'type': 'instance method', 'path': 'dom/element/prototype/cloneposition' }, +'Object.isArray': { 'name': 'Object.isArray', 'type': 'class method', 'path': 'language/object/isarray' }, +'Selector.matchElements': { 'name': 'Selector.matchElements', 'type': 'class method', 'path': 'dom/selector/matchelements' }, +'Object.inspect': { 'name': 'Object.inspect', 'type': 'class method', 'path': 'language/object/inspect' }, +'String#inspect': { 'name': 'String#inspect', 'type': 'instance method', 'path': 'language/string/prototype/inspect' }, +'Array#size': { 'name': 'Array#size', 'type': 'instance method', 'path': 'language/array/prototype/size' }, +'Ajax.Response#responseText': { 'name': 'Ajax.Response#responseText', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsetext' }, +'Element#getStyle': { 'name': 'Element#getStyle', 'type': 'instance method', 'path': 'dom/element/prototype/getstyle' }, +'String#parseQuery': { 'name': 'String#parseQuery', 'type': 'instance method', 'path': 'language/string/prototype/parsequery' }, +'Ajax.Response#responseJSON': { 'name': 'Ajax.Response#responseJSON', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsejson' }, +'Element#insert': { 'name': 'Element#insert', 'type': 'instance method', 'path': 'dom/element/prototype/insert' }, +'new Ajax.Updater': { 'name': 'new Ajax.Updater', 'type': 'constructor', 'path': 'ajax/ajax/updater/new' }, +'Selector#match': { 'name': 'Selector#match', 'type': 'instance method', 'path': 'dom/selector/prototype/match' }, +'Ajax.Response#readyState': { 'name': 'Ajax.Response#readyState', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/readystate' }, +'Enumerable#filter': { 'name': 'Enumerable#filter', 'type': 'instance method', 'path': 'language/enumerable/prototype/filter' }, +'Form.focusFirstElement': { 'name': 'Form.focusFirstElement', 'type': 'class method', 'path': 'dom/form/focusfirstelement' }, +'Ajax.Response#headerJSON': { 'name': 'Ajax.Response#headerJSON', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/headerjson' }, +'Form#enable': { 'name': 'Form#enable', 'type': 'instance method', 'path': 'dom/form/prototype/enable' }, +'Form.Element#activate': { 'name': 'Form.Element#activate', 'type': 'instance method', 'path': 'dom/form/element/prototype/activate' }, +'Prototype.BrowserFeatures.ElementExtensions': { 'name': 'Prototype.BrowserFeatures.ElementExtensions', 'type': 'class property', 'path': 'language/prototype/browserfeatures/elementextensions' }, +'Event#pointerX': { 'name': 'Event#pointerX', 'type': 'instance method', 'path': 'dom/event/prototype/pointerx' }, +'Object.extend': { 'name': 'Object.extend', 'type': 'class method', 'path': 'language/object/extend' }, +'DOM section': { 'name': 'DOM section', 'type': 'section', 'path': 'dom' }, +'document.viewport.getWidth': { 'name': 'document.viewport.getWidth', 'type': 'class method', 'path': 'dom/document/viewport/getwidth' }, +'Element.getOffsetParent': { 'name': 'Element.getOffsetParent', 'type': 'class method', 'path': 'dom/element/getoffsetparent' }, +'Object.toJSON': { 'name': 'Object.toJSON', 'type': 'class method', 'path': 'language/object/tojson' }, +'PeriodicalExecuter#stop': { 'name': 'PeriodicalExecuter#stop', 'type': 'instance method', 'path': 'language/periodicalexecuter/prototype/stop' }, +'Function#bindAsEventListener': { 'name': 'Function#bindAsEventListener', 'type': 'instance method', 'path': 'language/function/prototype/bindaseventlistener' }, +'Event#pointerY': { 'name': 'Event#pointerY', 'type': 'instance method', 'path': 'dom/event/prototype/pointery' }, +'Ajax.Response': { 'name': 'Ajax.Response', 'type': 'class', 'path': 'ajax/ajax/response' }, +'Hash#toJSON': { 'name': 'Hash#toJSON', 'type': 'instance method', 'path': 'language/hash/prototype/tojson' }, +'Hash#keys': { 'name': 'Hash#keys', 'type': 'instance method', 'path': 'language/hash/prototype/keys' }, +'Element#store': { 'name': 'Element#store', 'type': 'instance method', 'path': 'dom/element/prototype/store' }, +'Element.replace': { 'name': 'Element.replace', 'type': 'class method', 'path': 'dom/element/replace' }, +'Element.descendants': { 'name': 'Element.descendants', 'type': 'class method', 'path': 'dom/element/descendants' }, +'Prototype.emptyFunction': { 'name': 'Prototype.emptyFunction', 'type': 'class method', 'path': 'language/prototype/emptyfunction' }, +'Enumerable#reject': { 'name': 'Enumerable#reject', 'type': 'instance method', 'path': 'language/enumerable/prototype/reject' }, +'Enumerable#some': { 'name': 'Enumerable#some', 'type': 'instance method', 'path': 'language/enumerable/prototype/some' }, +'Enumerable#partition': { 'name': 'Enumerable#partition', 'type': 'instance method', 'path': 'language/enumerable/prototype/partition' }, +'Hash#update': { 'name': 'Hash#update', 'type': 'instance method', 'path': 'language/hash/prototype/update' }, +'Form#focusFirstElement': { 'name': 'Form#focusFirstElement', 'type': 'instance method', 'path': 'dom/form/prototype/focusfirstelement' }, +'Element#previousSiblings': { 'name': 'Element#previousSiblings', 'type': 'instance method', 'path': 'dom/element/prototype/previoussiblings' }, +'Element.clonePosition': { 'name': 'Element.clonePosition', 'type': 'class method', 'path': 'dom/element/cloneposition' }, +'Ajax.Response#status': { 'name': 'Ajax.Response#status', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/status' }, +'Element#nextSiblings': { 'name': 'Element#nextSiblings', 'type': 'instance method', 'path': 'dom/element/prototype/nextsiblings' }, +'Element.getLayout': { 'name': 'Element.getLayout', 'type': 'class method', 'path': 'dom/element/getlayout' }, +'Number#succ': { 'name': 'Number#succ', 'type': 'instance method', 'path': 'language/number/prototype/succ' }, +'Element#measure': { 'name': 'Element#measure', 'type': 'instance method', 'path': 'dom/element/prototype/measure' }, +'Element#update': { 'name': 'Element#update', 'type': 'instance method', 'path': 'dom/element/prototype/update' }, +'Element#stopObserving': { 'name': 'Element#stopObserving', 'type': 'instance method', 'path': 'dom/element/prototype/stopobserving' }, +'Element.identify': { 'name': 'Element.identify', 'type': 'class method', 'path': 'dom/element/identify' }, +'Element.hasAttribute': { 'name': 'Element.hasAttribute', 'type': 'class method', 'path': 'dom/element/hasattribute' }, +'document.viewport.getHeight': { 'name': 'document.viewport.getHeight', 'type': 'class method', 'path': 'dom/document/viewport/getheight' }, +'Try.these': { 'name': 'Try.these', 'type': 'class method', 'path': 'language/try/these' }, +'Element#adjacent': { 'name': 'Element#adjacent', 'type': 'instance method', 'path': 'dom/element/prototype/adjacent' }, +'Enumerable#size': { 'name': 'Enumerable#size', 'type': 'instance method', 'path': 'language/enumerable/prototype/size' }, +'new Ajax.Request': { 'name': 'new Ajax.Request', 'type': 'constructor', 'path': 'ajax/ajax/request/new' }, +'Element#hasAttribute': { 'name': 'Element#hasAttribute', 'type': 'instance method', 'path': 'dom/element/prototype/hasattribute' }, +'Function#wrap': { 'name': 'Function#wrap', 'type': 'instance method', 'path': 'language/function/prototype/wrap' }, +'document.loaded': { 'name': 'document.loaded', 'type': 'class property', 'path': 'dom/document/loaded' }, +'Element#classNames': { 'name': 'Element#classNames', 'type': 'instance method', 'path': 'dom/element/prototype/classnames' }, +'Element#empty': { 'name': 'Element#empty', 'type': 'instance method', 'path': 'dom/element/prototype/empty' }, +'Function#defer': { 'name': 'Function#defer', 'type': 'instance method', 'path': 'language/function/prototype/defer' }, +'Array#intersect': { 'name': 'Array#intersect', 'type': 'instance method', 'path': 'language/array/prototype/intersect' }, +'Element.previousSiblings': { 'name': 'Element.previousSiblings', 'type': 'class method', 'path': 'dom/element/previoussiblings' }, +'Form.Element.activate': { 'name': 'Form.Element.activate', 'type': 'class method', 'path': 'dom/form/element/activate' }, +'new Template': { 'name': 'new Template', 'type': 'constructor', 'path': 'language/template/new' }, +'Enumerable#findAll': { 'name': 'Enumerable#findAll', 'type': 'instance method', 'path': 'language/enumerable/prototype/findall' }, +'Form.reset': { 'name': 'Form.reset', 'type': 'class method', 'path': 'dom/form/reset' }, +'Function#curry': { 'name': 'Function#curry', 'type': 'instance method', 'path': 'language/function/prototype/curry' } +}; \ No newline at end of file diff --git a/doc/1.7_rc1/javascripts/prototype.js b/doc/1.7_rc1/javascripts/prototype.js new file mode 100644 index 000000000..9fe6e1243 --- /dev/null +++ b/doc/1.7_rc1/javascripts/prototype.js @@ -0,0 +1,4874 @@ +/* Prototype JavaScript framework, version 1.6.1 + * (c) 2005-2009 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.6.1', + + Browser: (function(){ + var ua = navigator.userAgent; + var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; + return { + IE: !!window.attachEvent && !isOpera, + Opera: isOpera, + WebKit: ua.indexOf('AppleWebKit/') > -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile.*Safari/.test(ua) + } + })(), + + BrowserFeatures: { + XPath: !!document.evaluate, + SelectorsAPI: !!document.querySelector, + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'); + var form = document.createElement('form'); + var isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + + +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +/* Based on Alex Arnell's inheritance implementation. */ + +var Class = (function() { + function subclass() {}; + function create() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value; + value = (function(m) { + return function() { return ancestor[m].apply(this, arguments); }; + })(property).wrap(method); + + value.valueOf = method.valueOf.bind(method); + value.toString = method.toString.bind(method); + } + this.prototype[property] = value; + } + + return this; + } + + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { + + var _toString = Object.prototype.toString; + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } + + function inspect(object) { + try { + if (isUndefined(object)) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : String(object); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + } + + function toJSON(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (isElement(object)) return; + + var results = []; + for (var property in object) { + var value = toJSON(object[property]); + if (!isUndefined(value)) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + } + + function toQueryString(object) { + return $H(object).toQueryString(); + } + + function toHTML(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + } + + function keys(object) { + var results = []; + for (var property in object) + results.push(property); + return results; + } + + function values(object) { + var results = []; + for (var property in object) + results.push(object[property]); + return results; + } + + function clone(object) { + return extend({ }, object); + } + + function isElement(object) { + return !!(object && object.nodeType == 1); + } + + function isArray(object) { + return _toString.call(object) == "[object Array]"; + } + + + function isHash(object) { + return object instanceof Hash; + } + + function isFunction(object) { + return typeof object === "function"; + } + + function isString(object) { + return _toString.call(object) == "[object String]"; + } + + function isNumber(object) { + return _toString.call(object) == "[object Number]"; + } + + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function() { + var a = merge(args, arguments); + return __method.apply(context, a); + } + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function(event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + } + } + + function curry() { + if (!arguments.length) return this; + var __method = this, args = slice.call(arguments, 0); + return function() { + var a = merge(args, arguments); + return __method.apply(this, a); + } + } + + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000 + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + } + + function defer() { + var args = update([0.01], arguments); + return this.delay.apply(this, args); + } + + function wrap(wrapper) { + var __method = this; + return function() { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + } + } + + function methodize() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + var a = update([this], arguments); + return __method.apply(null, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, (function() { + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { + var result = '', source = this, match; + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + } + + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); + count = Object.isUndefined(count) ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + } + + function scan(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + } + + function truncate(length, truncation) { + length = length || 30; + truncation = Object.isUndefined(truncation) ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + } + + function strip() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + } + + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } + + function stripScripts() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + } + + function extractScripts() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + } + + function evalScripts() { + return this.extractScripts().map(function(script) { return eval(script) }); + } + + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } + + + function toQueryParams(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + } + + function toArray() { + return this.split(''); + } + + function succ() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + } + + function times(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + } + + function camelize() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + } + + function capitalize() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + } + + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } + + function dasherize() { + return this.replace(/_/g, '-'); + } + + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } + + function toJSON() { + return this.inspect(true); + } + + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } + + function isJSON() { + var str = this; + if (str.blank()) return false; + str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + } + + function evalJSON(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + } + + function include(pattern) { + return this.indexOf(pattern) > -1; + } + + function startsWith(pattern) { + return this.indexOf(pattern) === 0; + } + + function endsWith(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + } + + function empty() { + return this == ''; + } + + function blank() { + return /^\s*$/.test(this); + } + + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); + } + + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim ? String.prototype.trim : strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + toJSON: toJSON, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (object && Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return (match[1] + ''); + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = (function() { + function each(iterator, context) { + var index = 0; + try { + this._each(function(value) { + iterator.call(context, value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + } + + function eachSlice(number, iterator, context) { + var index = -number, slices = [], array = this.toArray(); + if (number < 1) return array; + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + } + + function all(iterator, context) { + iterator = iterator || Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator.call(context, value, index); + if (!result) throw $break; + }); + return result; + } + + function any(iterator, context) { + iterator = iterator || Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator.call(context, value, index)) + throw $break; + }); + return result; + } + + function collect(iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function detect(iterator, context) { + var result; + this.each(function(value, index) { + if (iterator.call(context, value, index)) { + result = value; + throw $break; + } + }); + return result; + } + + function findAll(iterator, context) { + var results = []; + this.each(function(value, index) { + if (iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function grep(filter, iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(RegExp.escape(filter)); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function include(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + } + + function inGroupsOf(number, fillWith) { + fillWith = Object.isUndefined(fillWith) ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + } + + function inject(memo, iterator, context) { + this.each(function(value, index) { + memo = iterator.call(context, memo, value, index); + }); + return memo; + } + + function invoke(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + } + + function max(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value >= result) + result = value; + }); + return result; + } + + function min(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value < result) + result = value; + }); + return result; + } + + function partition(iterator, context) { + iterator = iterator || Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator.call(context, value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + } + + function pluck(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + } + + function reject(iterator, context) { + var results = []; + this.each(function(value, index) { + if (!iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function sortBy(iterator, context) { + return this.map(function(value, index) { + return { + value: value, + criteria: iterator.call(context, value, index) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + } + + function toArray() { + return this.map(); + } + + function zip() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + } + + function size() { + return this.toArray().length; + } + + function inspect() { + return '#'; + } + + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); +function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +Array.from = $A; + + +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available + + function each(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + } + if (!_each) _each = each; + + function clear() { + this.length = 0; + return this; + } + + function first() { + return this[0]; + } + + function last() { + return this[this.length - 1]; + } + + function compact() { + return this.select(function(value) { + return value != null; + }); + } + + function flatten() { + return this.inject([], function(array, value) { + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; + }); + } + + function without() { + var values = slice.call(arguments, 0); + return this.select(function(value) { + return !values.include(value); + }); + } + + function reverse(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + } + + function uniq(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + } + + function intersect(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + } + + + function clone() { + return slice.call(this, 0); + } + + function size() { + return this.length; + } + + function inspect() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } + + function toJSON() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (!Object.isUndefined(value)) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } + + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } + + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } + + function concat() { + var array = slice.call(this, 0), item; + for (var i = 0, length = arguments.length; i < length; i++) { + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); + } else { + array.push(item); + } + } + return array; + } + + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); + + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) + + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; + + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } + + function inspect() { + return '#'; + } + + function toJSON() { + return Object.toJSON(this.toObject()); + } + + function clone() { + return new Hash(this); + } + + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; +})()); + +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } + + function succ() { + return this + 1; + } + + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } + + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } + + function toJSON() { + return isFinite(this) ? this.toString() : 'null'; + } + + function abs() { + return Math.abs(this); + } + + function round() { + return Math.round(this); + } + + function ceil() { + return Math.ceil(this); + } + + function floor() { + return Math.floor(this); + } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + toJSON: toJSON, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; +})()); + +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + } + + function _each(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + } + + function include(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } + + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); + } +}); +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name) || null; + } catch (e) { return null; } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); + + + +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +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(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + + +(function(global) { + + var SETATTRIBUTE_IGNORES_NAME = (function(){ + var elForm = document.createElement("form"); + var elInput = document.createElement("input"); + var root = document.documentElement; + elInput.setAttribute("name", "test"); + elForm.appendChild(elInput); + root.appendChild(elForm); + var isBuggy = elForm.elements + ? (typeof elForm.elements.test == "undefined") + : null; + root.removeChild(elForm); + elForm = elInput = null; + return isBuggy; + })(); + + var element = global.Element; + global.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; +})(this); + +Element.cache = { }; +Element.idCounter = 1; + +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 = $(element); + element.style.display = 'none'; + return element; + }, + + show: function(element) { + element = $(element); + element.style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return Element.recursivelyCollect(element, 'parentNode'); + }, + + descendants: function(element) { + return Element.select(element, "*"); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return Element.recursivelyCollect(element, 'previousSibling'); + }, + + nextSiblings: function(element) { + return Element.recursivelyCollect(element, 'nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + 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(element); + return Object.isNumber(expression) ? ancestors[expression] : + Selector.findElement(ancestors, expression, index); + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = Element.previousSiblings(element); + return Object.isNumber(expression) ? previousSiblings[expression] : + Selector.findElement(previousSiblings, expression, index); + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = Element.nextSiblings(element); + return Object.isNumber(expression) ? nextSiblings[expression] : + Selector.findElement(nextSiblings, expression, index); + }, + + + select: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element, args); + }, + + adjacent: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = Element.readAttribute(element, 'id'); + if (id) return id; + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return Element.getDimensions(element).height; + }, + + getWidth: function(element) { + return Element.getDimensions(element).width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!Element.hasClassName(element, className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (ancestor.contains) + return ancestor.contains(element) && ancestor !== element; + + while (element = element.parentNode) + if (element == ancestor) return true; + + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Element.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 || value == 'auto') { + 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) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = Element.getStyle(element, 'display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + if (Prototype.Browser.Opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName.toUpperCase() == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'absolute') return element; + + var offsets = Element.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'relative') return element; + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + source = $(source); + var p = Element.viewportOffset(source); + + element = $(element); + var delta = [0, 0]; + var parent = null; + if (Element.getStyle(element, 'position') == 'absolute') { + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); + } + + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + +if (Prototype.Browser.Opera) { + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + if (!Element.visible(element)) return null; + + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } + } + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); +} + +else if (Prototype.Browser.IE) { + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return $(document.body) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( + function(proceed, element) { + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + return proceed(element); + } + ); + + 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) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = (function(){ + + var classProp = 'className'; + var forProp = 'for'; + + var el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'); + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + var f; + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + } + })(); + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr2, + src: v._getAttr2, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName.toUpperCase() == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if ('outerHTML' in document.documentElement) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + } else div.innerHTML = html; + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['', '
    ', 1], + TBODY: ['', '
    ', 2], + TR: ['', '
    ', 3], + TD: ['
    ', '
    ', 4], + SELECT: ['', 1] + } +}; + +(function() { + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD + }); +})(); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return !!(node && node.specified); + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')) + +Element.extend = (function() { + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2); + var el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } + return Prototype.K; + } + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || typeof element._extendedByPrototype != 'undefined' || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName.toUpperCase(); + + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + extendElementWith(element, methods); + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +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, { + "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 (Object.isArray(tagName)) 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; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + 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]; + + var element = document.createElement(tagName); + var proto = element['__proto__'] || element.constructor.prototype; + element = null; + return proto; + } + + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + + if (F.ElementExtensions) { + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + + +document.viewport = { + + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = [Element.Storage.UID++]; + uid = element._prototypeUID[0]; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + } +}); +/* Portions of the Selector class are derived from Jack Slocum's DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + + if (this.shouldUseSelectorsAPI()) { + this.mode = 'selectorsAPI'; + } else if (this.shouldUseXPath()) { + this.mode = 'xpath'; + this.compileXPathMatcher(); + } else { + this.mode = "normal"; + this.compileMatcher(); + } + + }, + + shouldUseXPath: (function() { + + var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ + var isBuggy = false; + if (document.evaluate && window.XPathResult) { + var el = document.createElement('div'); + el.innerHTML = '
    '; + + var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; + + var result = document.evaluate(xpath, el, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + + isBuggy = (result.snapshotLength !== 2); + el = null; + } + return isBuggy; + })(); + + return function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + if (IS_DESCENDANT_SELECTOR_BUGGY) return false; + + return true; + } + + })(), + + shouldUseSelectorsAPI: function() { + if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + + if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; + + if (!Selector._div) Selector._div = new Element('div'); + + try { + Selector._div.querySelector(this.expression); + } catch(e) { + return false; + } + + return true; + }, + + compileMatcher: function() { + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m, len = ps.length, name; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i"; + } +}); + +if (Prototype.BrowserFeatures.SelectorsAPI && + document.compatMode === 'BackCompat') { + Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ + var div = document.createElement('div'), + span = document.createElement('span'); + + div.id = "prototype_test_id"; + span.className = 'Test'; + div.appendChild(span); + var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); + div = span = null; + return isIgnored; + })(); +} + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: function(m) { + m[1] = m[1].toLowerCase(); + return new Template("[@#{1}]").evaluate(m); + }, + attr: function(m) { + m[1] = m[1].toLowerCase(); + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0)]", + 'checked': "[@checked]", + 'disabled': "[(@disabled) and (@type!='hidden')]", + 'enabled': "[not(@disabled) and (@type!='hidden')]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, v, len = p.length, name; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: [ + { name: 'laterSibling', re: /^\s*~\s*/ }, + { name: 'child', re: /^\s*>\s*/ }, + { name: 'adjacent', re: /^\s*\+\s*/ }, + { name: 'descendant', re: /^\s/ }, + + { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, + { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, + { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, + { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, + { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, + { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } + ], + + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); + } + }, + + handlers: { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + mark: function(nodes) { + var _true = Prototype.emptyFunction; + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = _true; + return nodes; + }, + + unmark: (function(){ + + var PROPERTIES_ATTRIBUTES_MAP = (function(){ + var el = document.createElement('div'), + isBuggy = false, + propName = '_countedByPrototype', + value = 'x' + el[propName] = value; + isBuggy = (el.getAttribute(propName) === value); + el = null; + return isBuggy; + })(); + + return PROPERTIES_ATTRIBUTES_MAP ? + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } : + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = void 0; + return nodes; + } + })(), + + index: function(parentNode, reverse, ofType) { + parentNode._countedByPrototype = Prototype.emptyFunction; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + }, + + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { + n._countedByPrototype = Prototype.emptyFunction; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + tagName: function(nodes, root, tagName, combinator) { + var uTagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() === uTagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + + if (root == document) { + if (!targetNode) return []; + if (!nodes) return [targetNode]; + } else { + if (!root.sourceIndex || root.sourceIndex < 1) { + var nodes = root.getElementsByTagName('*'); + for (var j = 0, node; node = nodes[j]; j++) { + if (node.id === id) return [node]; + } + } + } + + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._countedByPrototype) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (node.tagName == '!' || node.firstChild) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._countedByPrototype) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled && (!node.type || node.type !== 'hidden')) + results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, + '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, + '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + + '-').include('-' + (v || "").toUpperCase() + '-'); } + }, + + split: function(expression) { + var expressions = []; + expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + return expressions; + }, + + matchElements: function(elements, expression) { + var matches = $$(expression), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._countedByPrototype) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + expressions = Selector.split(expressions.join(',')); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +if (Prototype.Browser.IE) { + Object.extend(Selector.handlers, { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + if (node.tagName !== "!") a.push(node); + return a; + } + }); +} + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} + +var Form = { + reset: function(form) { + form = $(form); + form.reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return /^(?:input|select|textarea)$/i.test(element.tagName); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !(/^(?:button|reset|submit)$/i.test(element.type)))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; + +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; + }, + + select: function(element, value) { + if (Object.isUndefined(value)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, currentValue, single = !Object.isArray(value); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + currentValue = this.optionValue(opt); + if (single) { + if (currentValue == value) { + opt.selected = true; + return; + } + } + else opt.selected = value.include(currentValue); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +(function() { + + var Event = { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; + + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + + var _isButton; + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + _isButton = function(event, code) { + return event.button === buttonMap[code]; + }; + } else if (Prototype.Browser.WebKit) { + _isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + } else { + _isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + function isLeftClick(event) { return _isButton(event, 0) } + + function isMiddleClick(event) { return _isButton(event, 1) } + + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); + + var node = event.target, type = event.type, + currentTarget = event.currentTarget; + + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; + } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop + }; + + + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return '[object Event]' } + }); + + Event.extend = function(event, element) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + + Object.extend(event, { + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + + return Object.extend(event, methods); + }; + } else { + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; + Object.extend(Event.prototype, methods); + Event.extend = Prototype.K; + } + + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } + + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } + + if (respondersForEvent.pluck('handler').include(handler)) return false; + + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; + + if (event.eventName !== eventName) + return false; + + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } + + if (parent === element) return; + + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } + + responder.handler = handler; + respondersForEvent.push(responder); + return responder; + } + + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } + } + + var CACHE = []; + + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); + + if (Prototype.Browser.WebKit) + window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; + } + + function observe(element, eventName, handler) { + element = $(element); + + var responder = _createResponder(element, eventName, handler); + + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); + } + } else { + var actualEventName = _getDOMEventName(eventName); + + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } + + return element; + } + + function stopObserving(element, eventName, handler) { + element = $(element); + + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) return element; + + if (eventName && !handler) { + var responders = registry.get(eventName); + + if (Object.isUndefined(responders)) return element; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + return element; + } else if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key, responders = pair.value; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + }); + return element; + } + + var responders = registry.get(eventName); + + if (!responders) return; + + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + var actualEventName = _getDOMEventName(eventName); + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); + } + } else { + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; + + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); + + return Event.extend(event); + } + + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ + + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearTimeout(timer); + document.loaded = true; + document.fire('dom:loaded'); + } + + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } + + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; + } + fireContentLoadedEvent(); + } + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); + } else { + document.observe('readystatechange', checkReadyState); + if (window == top) + timer = pollDoScroll.defer(); + } + + Event.observe(window, 'load', fireContentLoadedEvent); +})(); + +Element.addMethods(); + +/*------------------------------- DEPRECATED -------------------------------*/ + +Hash.toQueryString = Object.toQueryString; + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); + }, + + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, + + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, + + After: function(element, content) { + return Element.insert(element, {after:content}); + } +}; + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Position = { + includeScrollOffsets: false, + + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +/*--------------------------------------------------------------------------*/ + +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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); + +/*--------------------------------------------------------------------------*/ diff --git a/doc/1.7_rc1/javascripts/tabs.js b/doc/1.7_rc1/javascripts/tabs.js new file mode 100644 index 000000000..7c974209f --- /dev/null +++ b/doc/1.7_rc1/javascripts/tabs.js @@ -0,0 +1,506 @@ +/** + * @author Ryan Johnson + * @copyright 2008 PersonalGrid Corporation + * @package LivePipe UI + * @license MIT + * @url http://livepipe.net/core + * @require prototype.js + */ + +if(typeof(Control) == 'undefined') + Control = {}; + +var $proc = function(proc){ + return typeof(proc) == 'function' ? proc : function(){return proc}; +}; + +var $value = function(value){ + return typeof(value) == 'function' ? value() : value; +}; + +Object.Event = { + extend: function(object){ + object._objectEventSetup = function(event_name){ + this._observers = this._observers || {}; + this._observers[event_name] = this._observers[event_name] || []; + }; + object.observe = function(event_name,observer){ + if(typeof(event_name) == 'string' && typeof(observer) != 'undefined'){ + this._objectEventSetup(event_name); + if(!this._observers[event_name].include(observer)) + this._observers[event_name].push(observer); + }else + for(var e in event_name) + this.observe(e,event_name[e]); + }; + object.stopObserving = function(event_name,observer){ + this._objectEventSetup(event_name); + if(event_name && observer) + this._observers[event_name] = this._observers[event_name].without(observer); + else if(event_name) + this._observers[event_name] = []; + else + this._observers = {}; + }; + object.observeOnce = function(event_name,outer_observer){ + var inner_observer = function(){ + outer_observer.apply(this,arguments); + this.stopObserving(event_name,inner_observer); + }.bind(this); + this._objectEventSetup(event_name); + this._observers[event_name].push(inner_observer); + }; + object.notify = function(event_name){ + this._objectEventSetup(event_name); + var collected_return_values = []; + var args = $A(arguments).slice(1); + try{ + for(var i = 0; i < this._observers[event_name].length; ++i) + collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null); + }catch(e){ + if(e == $break) + return false; + else + throw e; + } + return collected_return_values; + }; + if(object.prototype){ + object.prototype._objectEventSetup = object._objectEventSetup; + object.prototype.observe = object.observe; + object.prototype.stopObserving = object.stopObserving; + object.prototype.observeOnce = object.observeOnce; + object.prototype.notify = function(event_name){ + if(object.notify){ + var args = $A(arguments).slice(1); + args.unshift(this); + args.unshift(event_name); + object.notify.apply(object,args); + } + this._objectEventSetup(event_name); + var args = $A(arguments).slice(1); + var collected_return_values = []; + try{ + if(this.options && this.options[event_name] && typeof(this.options[event_name]) == 'function') + collected_return_values.push(this.options[event_name].apply(this,args) || null); + for(var i = 0; i < this._observers[event_name].length; ++i) + collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null); + }catch(e){ + if(e == $break) + return false; + else + throw e; + } + return collected_return_values; + }; + } + } +}; + +/* Begin Core Extensions */ + +//Element.observeOnce +Element.addMethods({ + observeOnce: function(element,event_name,outer_callback){ + var inner_callback = function(){ + outer_callback.apply(this,arguments); + Element.stopObserving(element,event_name,inner_callback); + }; + Element.observe(element,event_name,inner_callback); + } +}); + +//mouseenter, mouseleave +//from http://dev.rubyonrails.org/attachment/ticket/8354/event_mouseenter_106rc1.patch +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._prototypeEventID) return element._prototypeEventID[0]; + arguments.callee.id = arguments.callee.id || 1; + return element._prototypeEventID = [++arguments.callee.id]; + } + + function getDOMEventName(eventName) { + if (eventName && eventName.include(':')) return "dataavailable"; + //begin extension + if(!Prototype.Browser.IE){ + eventName = { + mouseenter: 'mouseover', + mouseleave: 'mouseout' + }[eventName] || eventName; + } + //end extension + return eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(element, eventName, handler) { + var id = getEventID(element); + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (!Event || !Event.extend || + (event.eventName && event.eventName != eventName)) + return false; + + Event.extend(event); + handler.call(element, event); + }; + + //begin extension + if(!(Prototype.Browser.IE) && ['mouseenter','mouseleave'].include(eventName)){ + wrapper = wrapper.wrap(function(proceed,event) { + var rel = event.relatedTarget; + var cur = event.currentTarget; + if(rel && rel.nodeType == Node.TEXT_NODE) + rel = rel.parentNode; + if(rel && rel != cur && !rel.descendantOf(cur)) + return proceed(event); + }); + } + //end extension + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var name = getDOMEventName(eventName); + + var wrapper = createWrapper(element, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, + + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return Event.extend(event); + } + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize() +}); + +//mouse:wheel +(function(){ + function wheel(event){ + var delta; + // normalize the delta + if(event.wheelDelta) // IE & Opera + delta = event.wheelDelta / 120; + else if (event.detail) // W3C + delta =- event.detail / 3; + if(!delta) + return; + var custom_event = Event.element(event).fire('mouse:wheel',{ + delta: delta + }); + if(custom_event.stopped){ + Event.stop(event); + return false; + } + } + document.observe('mousewheel',wheel); + document.observe('DOMMouseScroll',wheel); +})(); + +/* End Core Extensions */ + +//from PrototypeUI +var IframeShim = Class.create({ + initialize: function() { + this.element = new Element('iframe',{ + style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none', + src: 'javascript:void(0);', + frameborder: 0 + }); + $(document.body).insert(this.element); + }, + hide: function() { + this.element.hide(); + return this; + }, + show: function() { + this.element.show(); + return this; + }, + positionUnder: function(element) { + var element = $(element); + var offset = element.cumulativeOffset(); + var dimensions = element.getDimensions(); + this.element.setStyle({ + left: offset[0] + 'px', + top: offset[1] + 'px', + width: dimensions.width + 'px', + height: dimensions.height + 'px', + zIndex: element.getStyle('zIndex') - 1 + }).show(); + return this; + }, + setBounds: function(bounds) { + for(prop in bounds) + bounds[prop] += 'px'; + this.element.setStyle(bounds); + return this; + }, + destroy: function() { + if(this.element) + this.element.remove(); + return this; + } +}); + +/** + * @author Ryan Johnson + * @copyright 2008 PersonalGrid Corporation + * @package LivePipe UI + * @license MIT + * @url http://livepipe.net/control/tabs + * @require prototype.js, livepipe.js + */ + +/*global window, document, Prototype, $, $A, $H, $break, Class, Element, Event, Control */ + +if(typeof(Prototype) == "undefined") { + throw "Control.Tabs requires Prototype to be loaded."; } +if(typeof(Object.Event) == "undefined") { + throw "Control.Tabs requires Object.Event to be loaded."; } + +Control.Tabs = Class.create({ + initialize: function(tab_list_container,options){ + if(!$(tab_list_container)) { + throw "Control.Tabs could not find the element: " + tab_list_container; } + this.activeContainer = false; + this.activeLink = false; + this.containers = $H({}); + this.links = []; + Control.Tabs.instances.push(this); + this.options = { + beforeChange: Prototype.emptyFunction, + afterChange: Prototype.emptyFunction, + hover: false, + linkSelector: 'li a', + setClassOnContainer: false, + activeClassName: 'active', + defaultTab: 'first', + autoLinkExternal: true, + targetRegExp: /#(.+)$/, + showFunction: Element.show, + hideFunction: Element.hide + }; + Object.extend(this.options,options || {}); + (typeof(this.options.linkSelector == 'string') ? + $(tab_list_container).select(this.options.linkSelector) : + this.options.linkSelector($(tab_list_container)) + ).findAll(function(link){ + return (/^#/).exec((Prototype.Browser.WebKit ? decodeURIComponent(link.href) : link.href).replace(window.location.href.split('#')[0],'')); + }).each(function(link){ + this.addTab(link); + }.bind(this)); + this.containers.values().each(Element.hide); + if(this.options.defaultTab == 'first') { + this.setActiveTab(this.links.first()); + } else if(this.options.defaultTab == 'last') { + this.setActiveTab(this.links.last()); + } else { + this.setActiveTab(this.options.defaultTab); } + var targets = this.options.targetRegExp.exec(window.location); + if(targets && targets[1]){ + targets[1].split(',').each(function(target){ + this.setActiveTab(this.links.find(function(link){ + return link.key == target; + })); + }.bind(this)); + } + if(this.options.autoLinkExternal){ + $A(document.getElementsByTagName('a')).each(function(a){ + if(!this.links.include(a)){ + var clean_href = a.href.replace(window.location.href.split('#')[0],''); + if(clean_href.substring(0,1) == '#'){ + if(this.containers.keys().include(clean_href.substring(1))){ + $(a).observe('click',function(event,clean_href){ + this.setActiveTab(clean_href.substring(1)); + }.bindAsEventListener(this,clean_href)); + } + } + } + }.bind(this)); + } + }, + addTab: function(link){ + this.links.push(link); + link.key = link.getAttribute('href').replace(window.location.href.split('#')[0],'').split('#').last().replace(/#/,''); + var container = $(link.key); + if(!container) { + throw "Control.Tabs: #" + link.key + " was not found on the page."; } + this.containers.set(link.key,container); + link[this.options.hover ? 'onmouseover' : 'onclick'] = function(link){ + if(window.event) { + Event.stop(window.event); } + this.setActiveTab(link); + return false; + }.bind(this,link); + }, + setActiveTab: function(link){ + if(!link && typeof(link) == 'undefined') { + return; } + if(typeof(link) == 'string'){ + this.setActiveTab(this.links.find(function(_link){ + return _link.key == link; + })); + }else if(typeof(link) == 'number'){ + this.setActiveTab(this.links[link]); + }else{ + if(this.notify('beforeChange',this.activeContainer,this.containers.get(link.key)) === false) { + return; } + if(this.activeContainer) { + this.options.hideFunction(this.activeContainer); } + this.links.each(function(item){ + (this.options.setClassOnContainer ? $(item.parentNode) : item).removeClassName(this.options.activeClassName); + }.bind(this)); + (this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.activeClassName); + this.activeContainer = this.containers.get(link.key); + this.activeLink = link; + this.options.showFunction(this.containers.get(link.key)); + this.notify('afterChange',this.containers.get(link.key)); + } + }, + next: function(){ + this.links.each(function(link,i){ + if(this.activeLink == link && this.links[i + 1]){ + this.setActiveTab(this.links[i + 1]); + throw $break; + } + }.bind(this)); + }, + previous: function(){ + this.links.each(function(link,i){ + if(this.activeLink == link && this.links[i - 1]){ + this.setActiveTab(this.links[i - 1]); + throw $break; + } + }.bind(this)); + }, + first: function(){ + this.setActiveTab(this.links.first()); + }, + last: function(){ + this.setActiveTab(this.links.last()); + } +}); +Object.extend(Control.Tabs,{ + instances: [], + findByTabId: function(id){ + return Control.Tabs.instances.find(function(tab){ + return tab.links.find(function(link){ + return link.key == id; + }); + }); + } +}); +Object.Event.extend(Control.Tabs); diff --git a/doc/1.7_rc1/language/array/from/index.html b/doc/1.7_rc1/language/array/from/index.html new file mode 100644 index 000000000..7adcf7a96 --- /dev/null +++ b/doc/1.7_rc1/language/array/from/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array.from + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Array.from +

    + + + + +
    +
    +
    +
    +
    +
    Array.from(iterable) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/index.html b/doc/1.7_rc1/language/array/index.html new file mode 100644 index 000000000..19db7fda2 --- /dev/null +++ b/doc/1.7_rc1/language/array/index.html @@ -0,0 +1,291 @@ + + + + + Prototype v1.7_rc1 API documentation | Array + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Array +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Prototype extends all native JavaScript arrays with quite a few powerful +methods.

    + +

    This is done in two ways:

    + +
      +
    • It mixes in the Enumerable module, which brings in a ton of methods.
    • +
    • It adds quite a few extra methods, which are documented in this section.
    • +
    + +

    With Prototype, arrays become much, much more than the trivial objects we +used to manipulate, limiting ourselves to using their length property and +their [] indexing operator. They become very powerful objects that +greatly simplify the code for 99% of the common use cases involving them.

    + +
    Why you should stop using for...in to iterate
    + +

    Many JavaScript authors have been misled into using the for...in JavaScript +construct to loop over array elements. This kind of code just won't work +with Prototype.

    + +

    The ECMA 262 standard, which defines ECMAScript 3rd edition, supposedly +implemented by all major browsers including MSIE, defines ten methods +on Array (§15.4.4), including nice methods like concat, join, +pop, and push.

    + +

    This same standard explicitly defines that the for...in construct (§12.6.4) +exists to enumerate the properties of the object appearing on the right side +of the in keyword. Only properties specifically marked as non-enumerable +are ignored by such a loop. By default, the prototype and length +properties are so marked, which prevents you from enumerating over array +methods when using for...in. This comfort led developers to use for...in as a +shortcut for indexing loops, when it is not its actual purpose.

    + +

    However, Prototype has no way to mark the methods it adds to +Array.prototype as non-enumerable. Therefore, using for...in on arrays +when using Prototype will enumerate all extended methods as well, such as +those coming from the Enumerable module, and those Prototype puts in the +Array namespace (listed further below).

    + +
    What you should use instead
    + +

    You can revert to vanilla loops:

    + +
    for (var index = 0; index < myArray.length; ++index) {
    +  var item = myArray[index];
    +  // Your code working on item here...
    +}
    +
    +
    + +

    Or you can use iterators, such as Array#each:

    + +
    myArray.each(function(item) {
    +  // Your code working on item here...
    +});
    +
    +
    + +

    The inability to use for...in on arrays is not much of a burden: as you'll +see, most of what you used to loop over arrays for can be concisely done +using the new methods provided by Array or the mixed-in Enumerable +module. So manual loops should be fairly rare.

    + +
    A note on performance
    + +

    Should you have a very large array, using iterators with lexical closures +(anonymous functions that you pass to the iterators and that get invoked at +every loop iteration) in methods like Array#each — _or_ relying on +repetitive array construction (such as uniq), may yield unsatisfactory +performance. In such cases, you're better off writing manual indexing loops, +but take care then to cache the length property and use the prefix ++ +operator:

    + +
    // Custom loop with cached length property: maximum full-loop
    +// performance on very large arrays!
    +for (var index = 0, len = myArray.length; index < len; ++index) {
    +  var item = myArray[index];
    +  // Your code working on item here...
    +}
    +
    +
    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/clear/index.html b/doc/1.7_rc1/language/array/prototype/clear/index.html new file mode 100644 index 000000000..844740fd2 --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/clear/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#clear + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#clear +

    + + + + +
    +
    +
    +
    +
    +
    Array#clear() → Array
    + + +

    Clears the array (makes it empty) and returns the array reference.

    + +
    Example
    + +
    var guys = ['Sam', 'Justin', 'Andrew', 'Dan'];
    +guys.clear();
    +// -> []
    +guys
    +// -> []
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/clone/index.html b/doc/1.7_rc1/language/array/prototype/clone/index.html new file mode 100644 index 000000000..0870a4d0b --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/clone/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#clone +

    + + + + +
    +
    +
    +
    +
    +
    Array#clone() → Array
    + + +

    Returns a duplicate of the array, leaving the original array intact.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/compact/index.html b/doc/1.7_rc1/language/array/prototype/compact/index.html new file mode 100644 index 000000000..78a0f23ae --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/compact/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#compact + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#compact +

    + + + + +
    +
    +
    +
    +
    +
    Array#compact() → Array
    + + +

    Returns a copy of the array without any null or undefined values.

    + +
    Example
    + +
    var orig = [undefined, 'A', undefined, 'B', null, 'C'];
    +var copy = orig.compact();
    +// orig -> [undefined, 'A', undefined, 'B', null, 'C'];
    +// copy -> ['A', 'B', 'C'];
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/first/index.html b/doc/1.7_rc1/language/array/prototype/first/index.html new file mode 100644 index 000000000..c79c52806 --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/first/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#first + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#first +

    + + + + +
    +
    +
    +
    +
    +
    Array#first() → ?
    + + +

    Returns the array's first item (e.g., array[0]).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/flatten/index.html b/doc/1.7_rc1/language/array/prototype/flatten/index.html new file mode 100644 index 000000000..451a52b31 --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/flatten/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#flatten + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#flatten +

    + + + + +
    +
    +
    +
    +
    +
    Array#flatten() → Array
    + + +

    Returns a flattened (one-dimensional) copy of the array, leaving +the original array unchanged.

    + +

    Nested arrays are recursively injected inline. This can prove very +useful when handling the results of a recursive collection algorithm, +for instance.

    + +
    Example
    + +
    var a = ['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]];
    +var b = a.flatten();
    +// a -> ['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]]
    +// b -> ['frank', 'bob', 'lisa', 'jill', 'tom', 'sally']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/indexof/index.html b/doc/1.7_rc1/language/array/prototype/indexof/index.html new file mode 100644 index 000000000..dcf1aa736 --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/indexof/index.html @@ -0,0 +1,180 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#indexOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#indexOf +

    + + + + +
    +
    +
    +
    +
    +
    Array#indexOf(item[, offset = 0]) → Number
    +
      +
    • + item + (?) + – A value that may or may not be in the array. +
    • +
    • + offset + (Number) + – The number of initial items to skip before beginning the search. +
    • +
    + + +

    Returns the index of the first occurrence of item within the array, +or -1 if item doesn't exist in the array. Array#indexOf compares +items using strict equality (===).

    + +
    Examples
    + +
    [3, 5, 6, 1, 20].indexOf(1)
    +// -> 3
    + [3, 5, 6, 1, 20].indexOf(90)
    +// -> -1 (not found)
    + ['1', '2', '3'].indexOf(1);
    +// -> -1 (not found, 1 !== '1')
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/inspect/index.html b/doc/1.7_rc1/language/array/prototype/inspect/index.html new file mode 100644 index 000000000..e43adb33c --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/inspect/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Array#inspect() → String
    + + +

    Returns the debug-oriented string representation of an array.

    + +
    Example
    + +
    ['Apples', {good: 'yes', bad: 'no'}, 3, 34].inspect()
    +// -> "['Apples', [object Object], 3, 34]"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/intersect/index.html b/doc/1.7_rc1/language/array/prototype/intersect/index.html new file mode 100644 index 000000000..2e0a8383d --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/intersect/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#intersect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#intersect +

    + + + + +
    +
    +
    +
    +
    +
    Array#intersect(array) → Array
    +
      +
    • + array + (Array) + – A collection of values. +
    • +
    + + +

    Returns an array containing every item that is shared between the two +given arrays.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/last/index.html b/doc/1.7_rc1/language/array/prototype/last/index.html new file mode 100644 index 000000000..5ef6c9a8c --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/last/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#last + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#last +

    + + + + +
    +
    +
    +
    +
    +
    Array#last() → ?
    + + +

    Returns the array's last item (e.g., array[array.length - 1]).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/lastindexof/index.html b/doc/1.7_rc1/language/array/prototype/lastindexof/index.html new file mode 100644 index 000000000..5c916e389 --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/lastindexof/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#lastIndexOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#lastIndexOf +

    + + + + +
    +
    +
    +
    +
    +
    Array#lastIndexOf(item[, offset]) → Number
    +
      +
    • + item + (?) + – A value that may or may not be in the array. +
    • +
    • + offset + (Number) + – The number of items at the end to skip before beginning the search. +
    • +
    + + +

    Returns the position of the last occurrence of item within the array — or +-1 if item doesn't exist in the array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/reverse/index.html b/doc/1.7_rc1/language/array/prototype/reverse/index.html new file mode 100644 index 000000000..a2c4efa20 --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/reverse/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#reverse + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#reverse +

    + + + + +
    +
    +
    +
    +
    +
    Array#reverse([inline = true]) → Array
    +
      +
    • + inline + (Boolean) + – Whether to modify the array in place. Defaults to true. Clones the original array when false. +
    • +
    + + +

    Reverses the array's contents, optionally cloning it first.

    + +
    Examples
    + +
    // Making a copy
    +var nums = [3, 5, 6, 1, 20];
    +var rev = nums.reverse(false);
    +// nums -> [3, 5, 6, 1, 20]
    +// rev -> [20, 1, 6, 5, 3]
    + // Working inline
    +var nums = [3, 5, 6, 1, 20];
    +nums.reverse();
    +// nums -> [20, 1, 6, 5, 3]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/size/index.html b/doc/1.7_rc1/language/array/prototype/size/index.html new file mode 100644 index 000000000..21f717608 --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/size/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#size + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#size +

    + + + + +
    +
    +
    +
    +
    +
    Array#size() → Number
    + + +

    Returns the size of the array (e.g., array.length).

    + +

    This is just a local optimization of the mixed-in Enumerable#size +which avoids array cloning and uses the array's native length property.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/toarray/index.html b/doc/1.7_rc1/language/array/prototype/toarray/index.html new file mode 100644 index 000000000..1906b689a --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/toarray/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#toArray +

    + + + + +
    +
    +
    +
    +
    +
    Array#toArray() → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/uniq/index.html b/doc/1.7_rc1/language/array/prototype/uniq/index.html new file mode 100644 index 000000000..56733cc6d --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/uniq/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#uniq + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#uniq +

    + + + + +
    +
    +
    +
    +
    +
    Array#uniq([sorted = false]) → Array
    +
      +
    • + sorted + (Boolean) + – Whether the array has already been sorted. If true, a less-costly algorithm will be used. +
    • +
    + + +

    Produces a duplicate-free version of an array. If no duplicates are +found, the original array is returned.

    + +

    On large arrays when sorted is false, this method has a potentially +large performance cost.

    + +
    Examples
    + +
    [1, 3, 2, 1].uniq();
    +// -> [1, 2, 3]
    + ['A', 'a'].uniq();
    +// -> ['A', 'a'] (because String comparison is case-sensitive)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/array/prototype/without/index.html b/doc/1.7_rc1/language/array/prototype/without/index.html new file mode 100644 index 000000000..b97618691 --- /dev/null +++ b/doc/1.7_rc1/language/array/prototype/without/index.html @@ -0,0 +1,172 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#without + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#without +

    + + + + +
    +
    +
    +
    +
    +
    Array#without(value[, value...]) → Array
    +
      +
    • + value + (?) + – A value to exclude. +
    • +
    + + +

    Produces a new version of the array that does not contain any of the +specified values, leaving the original array unchanged.

    + +
    Examples
    + +
    [3, 5, 6].without(3)
    +// -> [5, 6]
    + [3, 5, 6, 20].without(20, 6)
    +// -> [3, 5]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/class/create/index.html b/doc/1.7_rc1/language/class/create/index.html new file mode 100644 index 000000000..443ba9a47 --- /dev/null +++ b/doc/1.7_rc1/language/class/create/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Class.create + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Class.create +

    + + + + +
    +
    +
    +
    +
    +
    Class.create([superclass][, methods...]) → Class
    +
      +
    • + superclass + (Class) + – The optional superclass to inherit methods from. +
    • +
    • + methods + (Object) + – An object whose properties will be "mixed-in" to the new class. Any number of mixins can be added; later mixins take precedence. +
    • +
    + + +

    Class.create creates a class and returns a constructor function for +instances of the class. Calling the constructor function (typically as +part of a new statement) will invoke the class's initialize method.

    + +

    Class.create accepts two kinds of arguments. If the first argument is +a Class, it's used as the new class's superclass, and all its methods +are inherited. Otherwise, any arguments passed are treated as objects, +and their methods are copied over ("mixed in") as instance methods of the +new class. In cases of method name overlap, later arguments take +precedence over earlier arguments.

    + +

    If a subclass overrides an instance method declared in a superclass, the +subclass's method can still access the original method. To do so, declare +the subclass's method as normal, but insert $super as the first +argument. This makes $super available as a method for use within the +function.

    + +

    To extend a class after it has been defined, use Class#addMethods.

    + +

    For details, see the +inheritance tutorial +on the Prototype website.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/class/index.html b/doc/1.7_rc1/language/class/index.html new file mode 100644 index 000000000..0eabe297c --- /dev/null +++ b/doc/1.7_rc1/language/class/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Class + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Class +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Manages Prototype's class-based OOP system.

    + +

    Refer to Prototype's web site for a tutorial on classes and +inheritance.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/class/prototype/addmethods/index.html b/doc/1.7_rc1/language/class/prototype/addmethods/index.html new file mode 100644 index 000000000..9be98c43e --- /dev/null +++ b/doc/1.7_rc1/language/class/prototype/addmethods/index.html @@ -0,0 +1,201 @@ + + + + + Prototype v1.7_rc1 API documentation | Class#addMethods + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Class#addMethods +

    + + + + +
    +
    +
    +
    +
    +
    Class#addMethods(methods) → Class
    +
      +
    • + methods + (Object) + – The methods to add to the class. +
    • +
    + + +

    Adds methods to an existing class.

    + +

    Class#addMethods is a method available on classes that have been +defined with Class.create. It can be used to add new instance methods +to that class, or overwrite existing methods, after the class has been +defined.

    + +

    New methods propagate down the inheritance chain. If the class has +subclasses, those subclasses will receive the new methods — even in +the context of $super calls. The new methods also propagate to instances +of the class and of all its subclasses, even those that have already been +instantiated.

    + +
    Examples
    + +
    var Animal = Class.create({
    +  initialize: function(name, sound) {
    +    this.name  = name;
    +    this.sound = sound;
    +  },
    +   speak: function() {
    +    alert(this.name + " says: " + this.sound + "!");
    +  }
    +});
    + // subclassing Animal
    +var Snake = Class.create(Animal, {
    +  initialize: function($super, name) {
    +    $super(name, 'hissssssssss');
    +  }
    +});
    + var ringneck = new Snake("Ringneck");
    +ringneck.speak();
    + //-> alerts "Ringneck says: hissssssss!"
    + // adding Snake#speak (with a supercall)
    +Snake.addMethods({
    +  speak: function($super) {
    +    $super();
    +    alert("You should probably run. He looks really mad.");
    +  }
    +});
    + ringneck.speak();
    +//-> alerts "Ringneck says: hissssssss!"
    +//-> alerts "You should probably run. He looks really mad."
    + // redefining Animal#speak
    +Animal.addMethods({
    +  speak: function() {
    +    alert(this.name + 'snarls: ' + this.sound + '!');
    +  }
    +});
    + ringneck.speak();
    +//-> alerts "Ringneck snarls: hissssssss!"
    +//-> alerts "You should probably run. He looks really mad."
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/date/index.html b/doc/1.7_rc1/language/date/index.html new file mode 100644 index 000000000..3c9cc7bd5 --- /dev/null +++ b/doc/1.7_rc1/language/date/index.html @@ -0,0 +1,157 @@ + + + + + Prototype v1.7_rc1 API documentation | Date + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Date +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Date object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/date/prototype/toisostring/index.html b/doc/1.7_rc1/language/date/prototype/toisostring/index.html new file mode 100644 index 000000000..f06ab27f7 --- /dev/null +++ b/doc/1.7_rc1/language/date/prototype/toisostring/index.html @@ -0,0 +1,152 @@ + + + + + Prototype v1.7_rc1 API documentation | Date#toISOString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Date#toISOString +

    + + + + +
    +
    +
    +
    +
    +
    Date#toISOString() → String
    + + +

    Produces a string representation of the date in ISO 8601 format. +The time zone is always UTC, as denoted by the suffix "Z".

    + +
    Example
    + +
    var d = new Date(1969, 11, 31, 19);
    +d.getTimezoneOffset();
    +//-> -180 (time offest is given in minutes.)
    +d.toISOString();
    +//-> '1969-12-31T16:00:00Z'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/date/prototype/tojson/index.html b/doc/1.7_rc1/language/date/prototype/tojson/index.html new file mode 100644 index 000000000..1fc2e38aa --- /dev/null +++ b/doc/1.7_rc1/language/date/prototype/tojson/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.7_rc1 API documentation | Date#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Date#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Date#toJSON() → String
    + + +

    Internally calls Date#toISOString.

    + +
    Example
    + +
    var d = new Date(1969, 11, 31, 19);
    +d.getTimezoneOffset();
    +//-> -180 (time offest is given in minutes.)
    +d.toJSON();
    +//-> '1969-12-31T16:00:00Z'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/dollara/index.html b/doc/1.7_rc1/language/dollara/index.html new file mode 100644 index 000000000..e4661c9a4 --- /dev/null +++ b/doc/1.7_rc1/language/dollara/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | $A + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $A +

    + + + + +
    +
    +
    +
    +
    +
    $A(iterable) → actualArray
    + + +

    Accepts an array-like collection (anything with numeric indices) and returns +its equivalent as an actual Array object. This method is a convenience +alias of Array.from, but is the preferred way of casting to an Array.

    + +

    The primary use of $A is to obtain an actual Array object based on +anything that could pass as an array (e.g. the NodeList or +HTMLCollection objects returned by numerous DOM methods, or the predefined +arguments reference within your functions).

    + +

    The reason you would want an actual Array is simple: +Prototype extends Array to equip it with numerous extra methods, +and also mixes in the Enumerable module, which brings in another +boatload of nifty methods. Therefore, in Prototype, actual Arrays trump +any other collection type you might otherwise get.

    + +

    The conversion performed is rather simple: null, undefined and false become +an empty array; any object featuring an explicit toArray method (as many Prototype +objects do) has it invoked; otherwise, we assume the argument "looks like an array" +(e.g. features a length property and the [] operator), and iterate over its components +in the usual way.

    + +

    When passed an array, $A makes a copy of that array and returns it.

    + +
    Examples
    + +

    The well-known DOM method document.getElementsByTagName() +doesn't return an Array, but a NodeList object that implements the basic array +"interface." Internet Explorer does not allow us to extend Enumerable onto NodeList.prototype, +so instead we cast the returned NodeList to an Array:

    + +
    var paras = $A(document.getElementsByTagName('p'));
    +paras.each(Element.hide);
    +$(paras.last()).show();
    +
    +
    + +

    Notice we had to use each and Element.hide because +$A doesn't perform DOM extensions, since the array could contain +anything (not just DOM elements). To use the Element#hide instance +method we first must make sure all the target elements are extended:

    + +
    $A(document.getElementsByTagName('p')).map(Element.extend).invoke('hide');
    +
    +
    + +

    Want to display your arguments easily? Array features a join method, but the arguments +value that exists in all functions does not inherit from Array. So, the tough +way, or the easy way?

    + +
    // The hard way...
    +function showArgs() {
    +  alert(Array.prototype.join.call(arguments, ', '));
    +}
    + // The easy way...
    +function showArgs() {
    +  alert($A(arguments).join(', '));
    +}
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/dollarh/index.html b/doc/1.7_rc1/language/dollarh/index.html new file mode 100644 index 000000000..f67e67489 --- /dev/null +++ b/doc/1.7_rc1/language/dollarh/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | $H + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $H +

    + + + + +
    +
    +
    +
    +
    +
    $H([obj]) → Hash
    + + +

    Creates a Hash (which is synonymous to "map" or "associative array" +for our purposes). A convenience wrapper around the Hash constructor, with a safeguard +that lets you pass an existing Hash object and get it back untouched (instead of +uselessly cloning it).

    + +

    The $H function is the shorter way to obtain a hash (prior to 1.5 final, it was +the only proper way of getting one).

    + +
    Example
    + +
    var h = $H({name: 'John', age: 26, country: 'Australia'});
    +// Equivalent to:
    +var h = new Hash({name: 'John', age: 26, country: 'Australia'});
    +// Can then be accessed the classic Hash way
    +h.get('country');
    +// -> 'Australia'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/dollarr/index.html b/doc/1.7_rc1/language/dollarr/index.html new file mode 100644 index 000000000..460400ca9 --- /dev/null +++ b/doc/1.7_rc1/language/dollarr/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | $R + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $R +

    + + + + +
    +
    +
    +
    +
    +
    $R(start, end[, exclusive = false]) → ObjectRange
    + + +

    Creates a new ObjectRange object. This method is a convenience wrapper +around the ObjectRange constructor, but $R is the preferred alias.

    + +

    ObjectRange instances represent a range of consecutive values, be they +numerical, textual, or of another type that semantically supports value +ranges. See the type's documentation for further details, and to discover +how your own objects can support value ranges.

    + +

    The $R function takes exactly the same arguments as the original +constructor: the lower and upper bounds (value of the same, proper +type), and whether the upper bound is exclusive or not. By default, the +upper bound is inclusive.

    + +
    Examples
    + +
    $R(0, 10).include(10)
    +// -> true
    + $A($R(0, 5)).join(', ')
    +// -> '0, 1, 2, 3, 4, 5'
    + $A($R('aa', 'ah')).join(', ')
    +// -> 'aa, ab, ac, ad, ae, af, ag, ah'
    + $R(0, 10, true).include(10)
    +// -> false
    + $R(0, 10, true).each(function(value) {
    +  // invoked 10 times for value = 0 to 9
    +});
    +
    +
    + +

    Note that ObjectRange mixes in the Enumerable module: this makes it +easy to convert a range to an Array (Enumerable provides the +Enumerable#toArray method, which makes the $A conversion +straightforward), or to iterate through values. (Note, however, that getting +the bounds back will be more efficiently done using the +ObjectRange#start and ObjectRange#end properties than calling the +Enumerable#min and Enumerable#max methods).

    + +
    Warning
    + +

    Be careful with String ranges: as described in its String#succ +method, it does not use alphabetical boundaries, but goes all the way +through the character table:

    + +
    $A($R('a', 'e'))
    +// -> ['a', 'b', 'c', 'd', 'e'], no surprise there
    + $A($R('ax', 'ba'))
    +// -> Ouch! Humongous array, starting as ['ax', 'ay', 'az', 'a{', 'a|', 'a}', 'a~'...]
    +
    +
    + +

    See ObjectRange for more information.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/dollarw/index.html b/doc/1.7_rc1/language/dollarw/index.html new file mode 100644 index 000000000..a7923886d --- /dev/null +++ b/doc/1.7_rc1/language/dollarw/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | $w + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $w +

    + + + + +
    +
    +
    +
    +
    +
    $w(String) → Array
    + + +

    Splits a string into an Array, treating all whitespace as delimiters. Equivalent +to Ruby's %w{foo bar} or Perl's qw(foo bar).

    + +

    This is one of those life-savers for people who just hate commas in literal arrays :-)

    + +

    Examples

    + +
    $w('apples bananas kiwis')
    +// -> ['apples', 'bananas', 'kiwis']
    +
    +
    + +

    This can slightly shorten code when writing simple iterations:

    + +
    $w('apples bananas kiwis').each(function(fruit){
    +  var message = 'I like ' + fruit
    +  // do something with the message
    +})
    +
    +
    + +

    This also becomes sweet when combined with Element functions:

    + +
    $w('ads navbar funkyLinks').each(Element.hide);
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/index.html b/doc/1.7_rc1/language/enumerable/index.html new file mode 100644 index 000000000..c288d8517 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/index.html @@ -0,0 +1,318 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + mixin Enumerable +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Enumerable provides a large set of useful methods for enumerations — +objects that act as collections of values. It is a cornerstone of +Prototype.

    + +

    Enumerable is a mixin: a set of methods intended not for standaone +use, but for incorporation into other objects.

    + +

    Prototype mixes Enumerable into several classes. The most visible cases +are Array and Hash, but you'll find it in less obvious spots as +well, such as in ObjectRange and various DOM- or Ajax-related objects.

    + +
    The context parameter
    + +

    Every method of Enumerable that takes an iterator also takes the "context +object" as the next (optional) parameter. The context object is what the +iterator will be bound to — what the keyword this will refer to inside +the iterator.

    + +
    var myObject = {};
    + ['foo', 'bar', 'baz'].each(function(name, index) {
    +  this[name] = index;
    +}, myObject); // we have specified the context
    + myObject;
    +// -> { foo: 0, bar: 1, baz: 2}
    +
    +
    + +

    If there is no context argument, the iterator function will execute in +the scope from which the Enumerable method itself was called.

    + +
    Mixing Enumerable into your own objects
    + +

    So, let's say you've created your very own collection-like object (say, +some sort of Set, or perhaps something that dynamically fetches data +ranges from the server side, lazy-loading style). You want to be able to +mix Enumerable in (and we commend you for it). How do you go about this?

    + +

    The Enumerable module basically makes only one requirement on your object: +it must provide a method named _each (note the leading underscore) that +will accept a function as its unique argument, and will contain the actual +"raw iteration" algorithm, invoking its argument with each element in turn.

    + +

    As detailed in the documentation for Enumerable#each, Enumerable +provides all the extra layers (handling iteration short-circuits, passing +numeric indices, etc.). You just need to implement the actual iteration, +as fits your internal structure.

    + +

    If you're still confused, just have a look at the Prototype source code for +Array, Hash, or ObjectRange. They all begin with their own +_each method, which should help you grasp the idea.

    + +

    Once you're done with this, you just need to mix Enumerable in, which +you'll usually do before defining your methods, so as to make sure whatever +overrides you provide for Enumerable methods will indeed prevail. In +short, your code will probably end up looking like this:

    + +
     var YourObject = Class.create(Enumerable, {
    +  initialize: function() { // with whatever constructor arguments you need
    +    // Your construction code
    +  },
    +   _each: function(iterator) {
    +    // Your iteration code, invoking iterator at every turn
    +  },
    +   // Your other methods here, including Enumerable overrides
    +});
    +
    +
    + +

    Then, obviously, your object can be used like this:

    + +
    var obj = new YourObject();
    +// Populate the collection somehow
    +obj.pluck('somePropName');
    +obj.invoke('someMethodName');
    +obj.size();
    +// etc.
    +
    +
    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/all/index.html b/doc/1.7_rc1/language/enumerable/prototype/all/index.html new file mode 100644 index 000000000..0dc69c66a --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/all/index.html @@ -0,0 +1,198 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#all + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#all +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#all([iterator = Prototype.K[, context]]) → Boolean
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Determines whether all the elements are "truthy" (boolean-equivalent to +true), either directly or through computation by the provided iterator. +Stops on the first falsy element found (e.g., the first element that +is boolean-equivalent to false, such as undefined, 0, or indeed +false);

    + +
    Examples
    + +
    [].all();
    +// -> true (empty arrays have no elements that could be falsy)
    + $R(1, 5).all();
    +// -> true (all values in [1..5] are truthy)
    + [0, 1, 2].all();
    +// -> false (with only one loop cycle: 0 is falsy)
    + [9, 10, 15].all(function(n) { return n >= 10; });
    +// -> false (the iterator returns false on 9)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/any/index.html b/doc/1.7_rc1/language/enumerable/prototype/any/index.html new file mode 100644 index 000000000..30f70f8de --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/any/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#any + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#any +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#any([iterator = Prototype.K[, context]]) → Boolean
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Determines whether at least one element is truthy (boolean-equivalent to +true), either directly or through computation by the provided iterator.

    + +
    Examples
    + +
    [].any();
    +// -> false (empty arrays have no elements that could be truthy)
    + $R(0, 2).any();
    +// -> true (on the second loop, 1 is truthy)
    + [2, 4, 6, 8, 10].any(function(n) { return n > 5; });
    +// -> true (the iterator will return true on 6)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/collect/index.html b/doc/1.7_rc1/language/enumerable/prototype/collect/index.html new file mode 100644 index 000000000..1d7f69ba4 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/collect/index.html @@ -0,0 +1,196 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#collect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#collect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#collect([iterator = Prototype.K[, context]]) → Array
    +
      +
    • + iterator + (Function) + – The iterator function to apply to each element in the enumeration. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns the result of applying iterator to each element. If no +iterator is provided, the elements are simply copied to the +returned array.

    + +
    Examples
    + +
    ['Hitch', "Hiker's", 'Guide', 'to', 'the', 'Galaxy'].collect(function(s) {
    +  return s.charAt(0).toUpperCase();
    +});
    +// -> ['H', 'H', 'G', 'T', 'T', 'G']
    + $R(1,5).collect(function(n) {
    +  return n * n;
    +});
    +// -> [1, 4, 9, 16, 25]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/detect/index.html b/doc/1.7_rc1/language/enumerable/prototype/detect/index.html new file mode 100644 index 000000000..2d3147205 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/detect/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#detect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#detect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#detect(iterator[, context]) → firstElement | undefined
    +
      +
    • + iterator + (Function) + – The iterator function to apply to each element in the enumeration. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns the first element for which the iterator returns a truthy value. +Aliased by the Enumerable#find method.

    + +
    Example
    + +
    [1, 7, -2, -4, 5].detect(function(n) { return n < 0; });
    +// -> -2
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/each/index.html b/doc/1.7_rc1/language/enumerable/prototype/each/index.html new file mode 100644 index 000000000..4f62edabc --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/each/index.html @@ -0,0 +1,196 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#each + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#each +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#each(iterator[, context]) → Enumerable
    +
      +
    • + iterator + (Function) + – A Function that expects an item in the collection as the first argument and a numerical index as the second. +
    • +
    • + context + (Object) + – The scope in which to call iterator. Affects what the keyword this means inside iterator. +
    • +
    + + +

    Calls iterator for each item in the collection.

    + +
    Examples
    + +
    ['one', 'two', 'three'].each(alert);
    +// Alerts "one", then alerts "two", then alerts "three"
    +
    +
    + +
    Built-In Variants
    + +

    Most of the common use cases for each are already available pre-coded +as other methods on Enumerable. Whether you want to find the first +matching item in an enumeration, or transform it, or determine whether it +has any (or all) values matching a particular condition, Enumerable +has a method to do that for you.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/eachslice/index.html b/doc/1.7_rc1/language/enumerable/prototype/eachslice/index.html new file mode 100644 index 000000000..145c2a16b --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/eachslice/index.html @@ -0,0 +1,204 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#eachSlice + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#eachSlice +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#eachSlice(number[, iterator = Prototype.K[, context]]) → Enumerable
    +
      +
    • + number + (Number) + – The number of items to include in each slice. +
    • +
    • + iterator + (Function) + – An optional function to use to transform each element before it's included in the slice; if this is not provided, the element itself is included. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Groups items into chunks of the given size. The final "slice" may have +fewer than number items; it won't "pad" the last group with empty +values. For that behavior, use Enumerable#inGroupsOf.

    + +
    Example
    + +
    var students = [
    +  { name: 'Sunny', age: 20 },
    +  { name: 'Audrey', age: 21 },
    +  { name: 'Matt', age: 20 },
    +  { name: 'Amelie', age: 26 },
    +  { name: 'Will', age: 21 }
    +];
    + students.eachSlice(3, function(student) {
    +  return student.name;
    +});
    +// -> [['Sunny', 'Audrey', 'Matt'], ['Amelie', 'Will']]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/entries/index.html b/doc/1.7_rc1/language/enumerable/prototype/entries/index.html new file mode 100644 index 000000000..ba80ea1c0 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/entries/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#entries + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#entries +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#entries() → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/every/index.html b/doc/1.7_rc1/language/enumerable/prototype/every/index.html new file mode 100644 index 000000000..a42b21258 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/every/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#every + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#every +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#every([iterator = Prototype.K[, context]]) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/filter/index.html b/doc/1.7_rc1/language/enumerable/prototype/filter/index.html new file mode 100644 index 000000000..74389fd5d --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/filter/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#filter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#filter +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#filter(iterator[, context]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/find/index.html b/doc/1.7_rc1/language/enumerable/prototype/find/index.html new file mode 100644 index 000000000..6df41ff77 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/find/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#find + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#find +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#find(iterator[, context]) → firstElement | undefined
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/findall/index.html b/doc/1.7_rc1/language/enumerable/prototype/findall/index.html new file mode 100644 index 000000000..48ebddf47 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/findall/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#findAll + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#findAll +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#findAll(iterator[, context]) → Array
    +
      +
    • + iterator + (Function) + – An iterator function to use to test the elements. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns all the elements for which the iterator returned a truthy value. +For the opposite operation, see Enumerable#reject.

    + +
    Example
    + +
    [1, 'two', 3, 'four', 5].findAll(Object.isString);
    +// -> ['two', 'four']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/grep/index.html b/doc/1.7_rc1/language/enumerable/prototype/grep/index.html new file mode 100644 index 000000000..4fb1ae3bc --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/grep/index.html @@ -0,0 +1,206 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#grep + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#grep +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#grep(filter[, iterator = Prototype.K[, context]]) → Array
    +
      +
    • + filter + (RegExp | String | Object) + – The filter to apply to elements. This can be a RegExp instance, a regular expression String, or any object with a match function. +
    • +
    • + iterator + (Function) + – An optional function to apply to selected elements before including them in the result. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns an array containing all of the elements for which the given +filter returns true (or a truthy value). If an iterator is provided, +it is used to produce the returned value for each selected element; this +is done after the element has been selected by the filter.

    + +

    If the given filter is a String, it is converted into a RegExp +object. To select elements, each element is passed into the filter's +match function, which should return a truthy value to select the element +or a falsy value not to. Note that the RegExp match function will +convert elements to Strings to perform matching.

    + +
    Examples
    + +
    // Get all strings containing a repeated letter
    +['hello', 'world', 'this', 'is', 'cool'].grep(/(.)\1/);
    +// -> ['hello', 'cool']
    + // Get all numbers ending with 0 or 5 and subtract 1 from them
    +$R(1, 30).grep(/[05]$/, function(n) { return n - 1; });
    +// -> [4, 9, 14, 19, 24, 29]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/include/index.html b/doc/1.7_rc1/language/enumerable/prototype/include/index.html new file mode 100644 index 000000000..150fe08d0 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/include/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#include +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#include(object) → Boolean
    +
      +
    • + object + (?) + – The object to look for. +
    • +
    + + +

    Determines whether a given object is in the enumerable or not, +based on the == comparison operator (equality with implicit type +conversion).

    + +
    Examples
    + +
    $R(1, 15).include(10);
    +// -> true
    + ['hello', 'world'].include('HELLO');
    +// -> false ('hello' != 'HELLO')
    + [1, 2, '3', '4', '5'].include(3);
    +// -> true ('3' == 3)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/ingroupsof/index.html b/doc/1.7_rc1/language/enumerable/prototype/ingroupsof/index.html new file mode 100644 index 000000000..59f8af372 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/ingroupsof/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#inGroupsOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inGroupsOf +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inGroupsOf(number[, fillWith = null]) → [group…]
    +
      +
    • + number + (Number) + – The number of items to include in each group. +
    • +
    • + fillWith + (Object) + – An optional filler to use if the last group needs any; defaults to null. +
    • +
    + + +

    Like Enumerable#eachSlice, but pads out the last chunk with the +specified value if necessary and doesn't support the iterator function.

    + +
    Examples
    + +
    var students = [
    +  { name: 'Sunny',  age: 20 },
    +  { name: 'Audrey', age: 21 },
    +  { name: 'Matt',   age: 20 },
    +  { name: 'Amelie', age: 26 },
    +  { name: 'Will',   age: 21 }
    +];
    + students.inGroupsOf(2, { name: '', age: 0 });
    +// -> [
    +//      [{ name: 'Sunny', age: 20 }, { name: 'Audrey', age: 21 }],
    +//      [{ name: 'Matt', age: 20 },  { name: 'Amelie', age: 26 }],
    +//      [{ name: 'Will', age: 21 },  { name: '', age: 0 }]
    +//    ]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/inject/index.html b/doc/1.7_rc1/language/enumerable/prototype/inject/index.html new file mode 100644 index 000000000..c9a588767 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/inject/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#inject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inject +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inject(accumulator, iterator[, context]) → accumulatedValue
    +
      +
    • + accumulator + (?) + – The initial value to which the iterator adds. +
    • +
    • + iterator + (Function) + – An iterator function used to build the accumulated result. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Incrementally builds a result value based on the successive results +of the iterator. This can be used for array construction, numerical +sums/averages, etc.

    + +

    The iterator function is called once for each element in the +enumeration, receiving the current value of the accumulator as its first +argument, the element as its second argument, and the element's index as +its third. It returns the new value for the accumulator.

    + +
    Examples
    + +
    $R(1,10).inject(0, function(acc, n) { return acc + n; });
    +// -> 55 (sum of 1 to 10)
    + ['a', 'b', 'c', 'd', 'e'].inject([], function(string, value, index) {
    +  if (index % 2 === 0) { // even numbers
    +    string += value;
    +  }
    +  return string;
    +});
    +// -> 'ace'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/inspect/index.html b/doc/1.7_rc1/language/enumerable/prototype/inspect/index.html new file mode 100644 index 000000000..a7b97140d --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/inspect/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inspect() → String
    + + +

    Returns the debug-oriented string representation of the object.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/invoke/index.html b/doc/1.7_rc1/language/enumerable/prototype/invoke/index.html new file mode 100644 index 000000000..9a1da5d83 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/invoke/index.html @@ -0,0 +1,194 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#invoke + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#invoke +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#invoke(methodName[, arg...]) → Array
    +
      +
    • + methodName + (String) + – The name of the method to invoke. +
    • +
    • + args + (?) + – Optional arguments to pass to the method. +
    • +
    + + +

    Invokes the same method, with the same arguments, for all items in a +collection. Returns an array of the results of the method calls.

    + +
    Examples
    + +
    ['hello', 'world'].invoke('toUpperCase');
    +// -> ['HELLO', 'WORLD']
    + ['hello', 'world'].invoke('substring', 0, 3);
    +// -> ['hel', 'wor']
    + $$('input').invoke('stopObserving', 'change');
    +// -> Stops observing the 'change' event on all input elements,
    +// returns an array of the element references.
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/map/index.html b/doc/1.7_rc1/language/enumerable/prototype/map/index.html new file mode 100644 index 000000000..c5a3b3820 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/map/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#map + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#map +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#map([iterator = Prototype.K[, context]]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/max/index.html b/doc/1.7_rc1/language/enumerable/prototype/max/index.html new file mode 100644 index 000000000..534ae4bb1 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/max/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#max + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#max +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#max([iterator = Prototype.K[, context]]) → maxValue
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns the maximum element (or element-based iterator result), or +undefined if the enumeration is empty. Elements are either compared +directly, or by first calling iterator and comparing returned values. +If multiple "max" elements (or results) are equivalent, the one closest +to the end of the enumeration is returned.

    + +

    If provided, iterator is called with two arguments: The element being +evaluated, and its index in the enumeration; it should return the value +max should consider (and potentially return).

    + +
    Examples
    + +
    ['c', 'b', 'a'].max();
    +// -> 'c'
    + [1, 3, '3', 2].max();
    +// -> '3' (because both 3 and '3' are "max", and '3' was later)
    + ['zero', 'one', 'two'].max(function(item) { return item.length; });
    +// -> 4
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/member/index.html b/doc/1.7_rc1/language/enumerable/prototype/member/index.html new file mode 100644 index 000000000..50cea9e85 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/member/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#member + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#member +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#member(object) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/min/index.html b/doc/1.7_rc1/language/enumerable/prototype/min/index.html new file mode 100644 index 000000000..c4a717dc1 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/min/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#min + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#min +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#min([iterator = Prototype.K[, context]]) → minValue
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns the minimum element (or element-based iterator result), or +undefined if the enumeration is empty. Elements are either compared +directly, or by first calling iterator and comparing returned values. +If multiple "min" elements (or results) are equivalent, the one closest +to the beginning of the enumeration is returned.

    + +

    If provided, iterator is called with two arguments: The element being +evaluated, and its index in the enumeration; it should return the value +min should consider (and potentially return).

    + +
    Examples
    + +
    ['c', 'b', 'a'].min();
    +// -> 'a'
    + [3, 1, '1', 2].min();
    +// -> 1 (because both 1 and '1' are "min", and 1 was earlier)
    + ['un', 'deux', 'trois'].min(function(item) { return item.length; });
    +// -> 2
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/partition/index.html b/doc/1.7_rc1/language/enumerable/prototype/partition/index.html new file mode 100644 index 000000000..e16c80d2f --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/partition/index.html @@ -0,0 +1,199 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#partition + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#partition +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#partition([iterator = Prototype.K[, context]]) → [TrueArray, FalseArray]
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Partitions the elements in two groups: those regarded as true, and those +considered false. By default, regular JavaScript boolean equivalence +(e.g., truthiness vs. falsiness) is used, but an iterator can be provided +that computes a boolean representation of the elements.

    + +

    Using partition is more efficient than using Enumerable#findAll and +then using Enumerable#reject because the enumeration is only processed +once.

    + +
    Examples
    + +
    ['hello', null, 42, false, true, , 17].partition();
    +// -> [['hello', 42, true, 17], [null, false, undefined]]
    + $R(1, 10).partition(function(n) {
    +  return 0 == n % 2;
    +});
    +// -> [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/pluck/index.html b/doc/1.7_rc1/language/enumerable/prototype/pluck/index.html new file mode 100644 index 000000000..40a401ed7 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/pluck/index.html @@ -0,0 +1,185 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#pluck + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#pluck +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#pluck(property) → Array
    +
      +
    • + property + (String) + – The name of the property to fetch. +
    • +
    + + +

    Pre-baked implementation for a common use-case of Enumerable#collect +and Enumerable#each: fetching the same property for all of the +elements. Returns an array of the property values.

    + +
    Example
    + +
    ['hello', 'world', 'this', 'is', 'nice'].pluck('length');
    +// -> [5, 5, 4, 2, 4]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/reject/index.html b/doc/1.7_rc1/language/enumerable/prototype/reject/index.html new file mode 100644 index 000000000..16e57383c --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/reject/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#reject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#reject +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#reject(iterator[, context]) → Array
    +
      +
    • + iterator + (Function) + – An iterator function to use to test the elements. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns all the elements for which the iterator returns a falsy value. +For the opposite operation, see Enumerable#findAll.

    + +
    Example
    + +
    [1, "two", 3, "four", 5].reject(Object.isString);
    +// -> [1, 3, 5]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/select/index.html b/doc/1.7_rc1/language/enumerable/prototype/select/index.html new file mode 100644 index 000000000..cf0a06148 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/select/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#select +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#select(iterator[, context]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/size/index.html b/doc/1.7_rc1/language/enumerable/prototype/size/index.html new file mode 100644 index 000000000..573ea3a59 --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/size/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#size + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#size +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#size() → Number
    + + +

    Returns the size of the enumeration.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/some/index.html b/doc/1.7_rc1/language/enumerable/prototype/some/index.html new file mode 100644 index 000000000..f106b6fdc --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/some/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#some + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#some +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#some([iterator = Prototype.K[, context]]) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/sortby/index.html b/doc/1.7_rc1/language/enumerable/prototype/sortby/index.html new file mode 100644 index 000000000..5b1732dad --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/sortby/index.html @@ -0,0 +1,196 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#sortBy + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#sortBy +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#sortBy(iterator[, context]) → Array
    +
      +
    • + iterator + (Function) + – The function to use to compute the criterion for each element in the enumeration. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Creates a custom-sorted array of the elements based on the criteria +computed, for each element, by the iterator. Computed criteria must have +well-defined ordering semantics (i.e. the < operator must exist between +any two criteria).

    + +

    Enumerable#sortBy does not guarantee a stable sort; adjacent +equivalent elements may be swapped.

    + +
    Example
    + +
    ['hello', 'world', 'this', 'is', 'nice'].sortBy(function(s) {
    +  return s.length;
    +});
    +// -> ['is', 'nice', 'this', 'world', 'hello']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/toarray/index.html b/doc/1.7_rc1/language/enumerable/prototype/toarray/index.html new file mode 100644 index 000000000..0ab3153af --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/toarray/index.html @@ -0,0 +1,178 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#toArray +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#toArray() → Array
    + + +

    Returns an Array containing the elements of the enumeration.

    + +
    Example
    + +
    $R(1, 5).toArray();
    +// -> [1, 2, 3, 4, 5]
    + $H({ name: 'Sunny', age: 20 }).toArray();
    +// -> [['name', 'Sunny'], ['age', 20]]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/enumerable/prototype/zip/index.html b/doc/1.7_rc1/language/enumerable/prototype/zip/index.html new file mode 100644 index 000000000..1a04f1eaf --- /dev/null +++ b/doc/1.7_rc1/language/enumerable/prototype/zip/index.html @@ -0,0 +1,203 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#zip + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#zip +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#zip(sequence...[, iterator = Prototype.K]) → Array
    +
      +
    • + sequence + (Object) + – A sequence to zip with this enumerable (there can be several of these if desired). +
    • +
    • + iterator + (Function) + – Optional function to use to transform the tuples once generated; this is always the last argument provided. +
    • +
    + + +

    Zips together (think of the zipper on a pair of trousers) 2+ sequences, +returning a new array of tuples. Each tuple is an array containing one +value per original sequence. Tuples can be transformed to something else +by applying the optional iterator on them.

    + +

    If supplied, iterator is called with each tuple as its only argument +and should return the value to use in place of that tuple.

    + +
    Examples
    + +
    var firstNames = ['Jane', 'Nitin', 'Guy'];
    +var lastNames  = ['Doe',  'Patel', 'Forcier'];
    +var ages       = [23,     41,      17];
    + firstNames.zip(lastNames);
    +// -> [['Jane', 'Doe'], ['Nitin', 'Patel'], ['Guy', 'Forcier']]
    + firstNames.zip(lastNames, ages);
    +// -> [['Jane', 'Doe', 23], ['Nitin', 'Patel', 41], ['Guy', 'Forcier', 17]]
    + firstNames.zip(lastNames, ages, function(tuple) {
    +  return tuple[0] + ' ' + tuple[1] + ' is ' + tuple[2];
    +});
    +// -> ['Jane Doe is 23', 'Nitin Patel is 41', 'Guy Forcier is 17']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/index.html b/doc/1.7_rc1/language/function/index.html new file mode 100644 index 000000000..dd16c417e --- /dev/null +++ b/doc/1.7_rc1/language/function/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Function + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Function +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Function object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/prototype/argumentnames/index.html b/doc/1.7_rc1/language/function/prototype/argumentnames/index.html new file mode 100644 index 000000000..49d1e642a --- /dev/null +++ b/doc/1.7_rc1/language/function/prototype/argumentnames/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#argumentNames + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#argumentNames +

    + + + + +
    +
    +
    +
    +
    +
    Function#argumentNames() → Array
    + + +

    Reads the argument names as stated in the function definition and returns +the values as an array of strings (or an empty array if the function is +defined without parameters).

    + +
    Examples
    + +
    function fn(foo, bar) {
    +  return foo + bar;
    +}
    +fn.argumentNames();
    +//-> ['foo', 'bar']
    + Prototype.emptyFunction.argumentNames();
    +//-> []
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/prototype/bind/index.html b/doc/1.7_rc1/language/function/prototype/bind/index.html new file mode 100644 index 000000000..cbb140843 --- /dev/null +++ b/doc/1.7_rc1/language/function/prototype/bind/index.html @@ -0,0 +1,219 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#bind + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#bind +

    + + + + +
    +
    +
    +
    +
    +
    Function#bind(context[, args...]) → Function
    +
      +
    • + context + (Object) + – The object to bind to. +
    • +
    • + args + (?) + – Optional additional arguments to curry for the function. +
    • +
    + + +

    Binds this function to the given context by wrapping it in another +function and returning the wrapper. Whenever the resulting "bound" +function is called, it will call the original ensuring that this is set +to context. Also optionally curries arguments for the function.

    + +
    Examples
    + +

    A typical use of Function#bind is to ensure that a callback (event +handler, etc.) that is an object method gets called with the correct +object as its context (this value):

    + +
    var AlertOnClick = Class.create({
    +  initialize: function(msg) {
    +    this.msg = msg;
    +  },
    +  handleClick: function(event) {
    +    event.stop();
    +    alert(this.msg);
    +  }
    +});
    +var myalert = new AlertOnClick("Clicked!");
    +$('foo').observe('click', myalert.handleClick); // <= WRONG
    +// -> If 'foo' is clicked, the alert will be blank; "this" is wrong
    +$('bar').observe('click', myalert.handleClick.bind(myalert)); // <= RIGHT
    +// -> If 'bar' is clicked, the alert will be "Clicked!"
    +
    +
    + +

    bind can also curry (burn in) arguments for the function if you +provide them after the context argument:

    + +
    var Averager = Class.create({
    +  initialize: function() {
    +    this.count = 0;
    +    this.total = 0;
    +  },
    +  add: function(addend) {
    +    ++this.count;
    +    this.total += addend;
    +  },
    +  getAverage: function() {
    +    return this.count == 0 ? NaN : this.total / this.count;
    +  }
    +});
    +var a = new Averager();
    +var b = new Averager();
    +var aAdd5 = a.add.bind(a, 5);   // Bind to a, curry 5
    +var aAdd10 = a.add.bind(a, 10); // Bind to a, curry 10
    +var bAdd20 = b.add.bind(b, 20); // Bind to b, curry 20
    +aAdd5();
    +aAdd10();
    +bAdd20();
    +bAdd20();
    +alert(a.getAverage());
    +// -> Alerts "7.5" (average of [5, 10])
    +alert(b.getAverage());
    +// -> Alerts "20" (average of [20, 20])
    +
    +
    + +

    (To curry without binding, see Function#curry.)

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/prototype/bindaseventlistener/index.html b/doc/1.7_rc1/language/function/prototype/bindaseventlistener/index.html new file mode 100644 index 000000000..d5cb66674 --- /dev/null +++ b/doc/1.7_rc1/language/function/prototype/bindaseventlistener/index.html @@ -0,0 +1,211 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#bindAsEventListener + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#bindAsEventListener +

    + + + + +
    +
    +
    +
    +
    +
    Function#bindAsEventListener(context[, args...]) → Function
    +
      +
    • + context + (Object) + – The object to bind to. +
    • +
    • + args + (?) + – Optional arguments to curry after the event argument. +
    • +
    + + +

    An event-specific variant of Function#bind which ensures the function +will recieve the current event object as the first argument when +executing.

    + +

    It is not necessary to use bindAsEventListener for all bound event +handlers; Function#bind works well for the vast majority of cases. +bindAsEventListener is only needed when:

    + +
      +
    • Using old-style DOM0 handlers rather than handlers hooked up via +Event.observe, because bindAsEventListener gets the event object +from the right place (even on MSIE). (If you're using Event.observe, +that's already handled.)
    • +
    • You want to bind an event handler and curry additional arguments but +have those arguments appear after, rather than before, the event object. +This mostly happens if the number of arguments will vary, and so you +want to know the event object is the first argument.
    • +
    + +
    Example
    + +
    var ContentUpdater = Class.create({
    +  initialize: function(initialData) {
    +    this.data = Object.extend({}, initialData);
    +  },
    +  // On an event, update the content in the elements whose
    +  // IDs are passed as arguments from our data
    +  updateTheseHandler: function(event) {
    +    var argIndex, id, element;
    +    event.stop();
    +    for (argIndex = 1; argIndex < arguments.length; ++argIndex) {
    +      id = arguments[argIndex];
    +      element = $(id);
    +      if (element) {
    +        element.update(String(this.data[id]).escapeHTML());
    +      }
    +    }
    +  }
    +});
    +var cu = new ContentUpdater({
    +  dispName: 'Joe Bloggs',
    +  dispTitle: 'Manager <provisional>',
    +  dispAge: 47
    +});
    +// Using bindAsEventListener because of the variable arg lists:
    +$('btnUpdateName').observe('click',
    +  cu.updateTheseHandler.bindAsEventListener(cu, 'dispName')
    +);
    +$('btnUpdateAll').observe('click',
    +  cu.updateTheseHandler.bindAsEventListener(cu, 'dispName', 'dispTitle', 'dispAge')
    +);
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/prototype/curry/index.html b/doc/1.7_rc1/language/function/prototype/curry/index.html new file mode 100644 index 000000000..0e1debf51 --- /dev/null +++ b/doc/1.7_rc1/language/function/prototype/curry/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#curry + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#curry +

    + + + + +
    +
    +
    +
    +
    +
    Function#curry(args...) → Function
    +
      +
    • + args + (?) + – The arguments to curry. +
    • +
    + + +

    Curries (burns in) arguments to a function, returning a new function +that when called with call the original passing in the curried arguments +(along with any new ones):

    + +
    function showArguments() {
    +  alert($A(arguments).join(', '));
    +}
    +showArguments(1, 2,, 3);
    +// -> alerts "1, 2, 3"
    + var f = showArguments.curry(1, 2, 3);
    +f('a', 'b');
    +// -> alerts "1, 2, 3, a, b"
    +
    +
    + +

    Function#curry works just like Function#bind without the initial +context argument. Use bind if you need to curry arguments and set +context at the same time.

    + +

    The name "curry" comes from mathematics.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/prototype/defer/index.html b/doc/1.7_rc1/language/function/prototype/defer/index.html new file mode 100644 index 000000000..0d2d0bc39 --- /dev/null +++ b/doc/1.7_rc1/language/function/prototype/defer/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#defer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#defer +

    + + + + +
    +
    +
    +
    +
    +
    Function#defer(args...) → Number
    +
      +
    • + args + (?) + – Optional arguments to pass into the function. +
    • +
    + + +

    Schedules the function to run as soon as the interpreter is idle.

    + +

    A "deferred" function will not run immediately; rather, it will run as soon +as the interpreter's call stack is empty.

    + +

    Behaves much like window.setTimeout with a delay set to 0. Returns an +ID that can be used to clear the timeout with window.clearTimeout before +it runs.

    + +
    Example
    + +
    function showMsg(msg) {
    +  alert(msg);
    +}
    + showMsg("One");
    +showMsg.defer("Two");
    +showMsg("Three");
    +// Alerts "One", then "Three", then (after a brief pause) "Two"
    +// Note that "Three" happens before "Two"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/prototype/delay/index.html b/doc/1.7_rc1/language/function/prototype/delay/index.html new file mode 100644 index 000000000..3b1e769af --- /dev/null +++ b/doc/1.7_rc1/language/function/prototype/delay/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#delay + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#delay +

    + + + + +
    +
    +
    +
    +
    +
    Function#delay(timeout[, args...]) → Number
    +
      +
    • + timeout + (Number) + – The time, in seconds, to wait before calling the function. +
    • +
    • + args + (?) + – Optional arguments to pass to the function when calling it. +
    • +
    + + +

    Schedules the function to run after the specified amount of time, passing +any arguments given.

    + +

    Behaves much like window.setTimeout, but the timeout is in seconds +rather than milliseconds. Returns an integer ID that can be used to +clear the timeout with window.clearTimeout before it runs.

    + +

    To schedule a function to run as soon as the interpreter is idle, use +Function#defer.

    + +
    Example
    + +
    function showMsg(msg) {
    +  alert(msg);
    +}
    +showMsg.delay(0.1, "Hi there!");
    +// -> Waits a 10th of a second, then alerts "Hi there!"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/prototype/methodize/index.html b/doc/1.7_rc1/language/function/prototype/methodize/index.html new file mode 100644 index 000000000..649e453a7 --- /dev/null +++ b/doc/1.7_rc1/language/function/prototype/methodize/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#methodize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#methodize +

    + + + + +
    +
    +
    +
    +
    +
    Function#methodize() → Function
    + + +

    Wraps the function inside another function that, when called, pushes +this to the original function as the first argument (with any further +arguments following it).

    + +

    The methodize method transforms the original function that has an +explicit first argument to a function that passes this (the current +context) as an implicit first argument at call time. It is useful when we +want to transform a function that takes an object to a method of that +object or its prototype, shortening its signature by one argument.

    + +
    Example
    + +
    // A function that sets a name on a target object
    +function setName(target, name) {
    +  target.name = name;
    +}
    + // Use it
    +obj = {};
    +setName(obj, 'Fred');
    +obj.name;
    +// -> "Fred"
    + // Make it a method of the object
    +obj.setName = setName.methodize();
    + // Use the method instead
    +obj.setName('Barney');
    +obj.name;
    +// -> "Barney"
    +
    +
    + +

    The example above is quite simplistic. It's more useful to copy methodized +functions to object prototypes so that new methods are immediately shared +among instances. In the Prototype library, methodize is used in various +places such as the DOM module, so that (for instance) you can hide an +element either by calling the static version of Element.hide and passing in +an element reference or ID, like so:

    + +
    Element.hide('myElement');
    +
    +
    + +

    ...or if you already have an element reference, just calling the +methodized form instead:

    + +
    myElement.hide();
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/function/prototype/wrap/index.html b/doc/1.7_rc1/language/function/prototype/wrap/index.html new file mode 100644 index 000000000..4a33f7a06 --- /dev/null +++ b/doc/1.7_rc1/language/function/prototype/wrap/index.html @@ -0,0 +1,191 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#wrap + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#wrap +

    + + + + +
    +
    +
    +
    +
    +
    Function#wrap(wrapper) → Function
    +
      +
    • + wrapper + (Function) + – The function to use as a wrapper. +
    • +
    + + +

    Returns a function "wrapped" around the original function.

    + +

    Function#wrap distills the essence of aspect-oriented programming into +a single method, letting you easily build on existing functions by +specifying before and after behavior, transforming the return value, or +even preventing the original function from being called.

    + +

    The wraper function is called with this signature:

    + +
    function wrapper(callOriginal[, args...])
    +
    +
    + +

    ...where callOriginal is a function that can be used to call the +original (wrapped) function (or not, as appropriate). (callOriginal is +not a direct reference to the original function, there's a layer of +indirection in-between that sets up the proper context [this value] for +it.)

    + +
    Example
    + +
    // Wrap String#capitalize so it accepts an additional argument
    +String.prototype.capitalize = String.prototype.capitalize.wrap(
    +  function(callOriginal, eachWord) {
    +    if (eachWord && this.include(" ")) {
    +      // capitalize each word in the string
    +      return this.split(" ").invoke("capitalize").join(" ");
    +    } else {
    +      // proceed using the original function
    +      return callOriginal();
    +    }
    +  });
    + "hello world".capitalize();
    +// -> "Hello world" (only the 'H' is capitalized)
    +"hello world".capitalize(true);
    +// -> "Hello World" (both 'H' and 'W' are capitalized)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/index.html b/doc/1.7_rc1/language/hash/index.html new file mode 100644 index 000000000..d4ce9ca42 --- /dev/null +++ b/doc/1.7_rc1/language/hash/index.html @@ -0,0 +1,221 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Hash +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A set of key/value pairs.

    + +

    Hash can be thought of as an associative array, binding unique keys to +values (which are not necessarily unique), though it can not guarantee +consistent order its elements when iterating. Because of the nature of +JavaScript, every object is in fact a hash; but Hash adds a number of +methods that let you enumerate keys and values, iterate over key/value +pairs, merge two hashes together, and much more.

    + +
    Creating a hash
    + +

    You can create a Hash either via new Hash() or the convenience alias +$H(); there is *no* difference between them. In either case, you may +optionally pass in an object to seed the Hash. If you pass in a Hash, +it will be cloned.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Hash

    +
    +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/new/index.html b/doc/1.7_rc1/language/hash/new/index.html new file mode 100644 index 000000000..f3fa9af5f --- /dev/null +++ b/doc/1.7_rc1/language/hash/new/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | new Hash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Hash +

    + + + + +
    +
    +
    +
    +
    +
    new([object])
    + + +

    Creates a new Hash. If object is given, the new hash will be populated +with all the object's properties. See $H.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/clone/index.html b/doc/1.7_rc1/language/hash/prototype/clone/index.html new file mode 100644 index 000000000..76f5ea325 --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/clone/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#clone +

    + + + + +
    +
    +
    +
    +
    +
    Hash#clone() → Hash
    + + +

    Returns a clone of this Hash.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/each/index.html b/doc/1.7_rc1/language/hash/prototype/each/index.html new file mode 100644 index 000000000..b245f342d --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/each/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#each + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#each +

    + + + + +
    +
    +
    +
    +
    +
    Hash#each(iterator[, context]) → Hash
    +
      +
    • + iterator + (Function) + – A function that expects each item in the Hash as the first argument and a numerical index as the second. +
    • +
    • + context + (Object) + – The scope in which to call iterator. Determines what this means inside iterator. +
    • +
    + + +

    Iterates over the name/value pairs in the hash.

    + +

    This is actually just the #each method from the +mixed-in Enumerable module. It is documented here to describe the +structure of the elements passed to the iterator and the order of +iteration.

    + +

    The iterator's first argument (the "item") is an object with two +properties:

    + +
      +
    • key: the key name as a String
    • +
    • value: the corresponding value (which may be undefined)
    • +
    + +

    The order of iteration is implementation-dependent, as it relies on +the order of the native for..in loop. Although most modern +implementations exhibit ordered behavior, this is not standardized and +may not always be the case, and so cannot be relied upon.

    + +
    Example
    + +
    var h = $H({version: 1.6, author: 'The Core Team'});
    + h.each(function(pair) {
    +  alert(pair.key + ' = "' + pair.value + '"');
    +});
    +// Alerts 'version = "1.6"' and 'author = "The Core Team"'
    +// -or-
    +// Alerts 'author = "The Core Team"' and 'version = "1.6"'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/get/index.html b/doc/1.7_rc1/language/hash/prototype/get/index.html new file mode 100644 index 000000000..bfc626680 --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/get/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#get + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#get +

    + + + + +
    +
    +
    +
    +
    +
    Hash#get(key) → value
    + + +

    Returns the stored value for the given key.

    + +
    Examples
    + +
    var h = new Hash({a: 'apple', b: 'banana', c: 'coconut'});
    +h.get('a');
    +// -> 'apple'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/index/index.html b/doc/1.7_rc1/language/hash/prototype/index/index.html new file mode 100644 index 000000000..e5f34095e --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/index/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#index + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#index +

    + + + + +
    +
    +
    +
    +
    +
    Hash#index(value) → String
    + + +

    Returns the first key in the hash whose value matches value. +Returns false if there is no such key.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/inspect/index.html b/doc/1.7_rc1/language/hash/prototype/inspect/index.html new file mode 100644 index 000000000..b4a7cf497 --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/inspect/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Hash#inspect() → String
    + + +

    Returns the debug-oriented string representation of the Hash.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/keys/index.html b/doc/1.7_rc1/language/hash/prototype/keys/index.html new file mode 100644 index 000000000..d8ba6a60a --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/keys/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#keys + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#keys +

    + + + + +
    +
    +
    +
    +
    +
    Hash#keys() → [String…]
    + + +

    Provides an Array containing the keys for items stored in the hash.

    + +

    The order of the keys is not guaranteed.

    + +
    Example
    + +
    var h = $H({one: "uno", two: "due", three: "tre"});
    +h.keys();
    +// -> ["one", "three", "two"] (these may be in any order)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/merge/index.html b/doc/1.7_rc1/language/hash/prototype/merge/index.html new file mode 100644 index 000000000..50bc41e80 --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/merge/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#merge + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#merge +

    + + + + +
    +
    +
    +
    +
    +
    Hash#merge(object) → Hash
    +
      +
    • + object + (Object | Hash) + – The object to merge with this hash to produce the resulting hash. +
    • +
    + + +

    Returns a new Hash instance with object's key/value pairs merged in; +this hash remains unchanged.

    + +

    To modify the original hash in place, use Hash#update.

    + +
    Example
    + +
    var h = $H({one: "uno", two: "due"});
    +var h2 = h.merge({three: "tre"});
    +h.keys();
    +// -> ["one", "two"] (unchanged)
    +h2.keys();
    +// -> ["one", "two", "three"] (has merged contents)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/set/index.html b/doc/1.7_rc1/language/hash/prototype/set/index.html new file mode 100644 index 000000000..165b091fd --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/set/index.html @@ -0,0 +1,181 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#set + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#set +

    + + + + +
    +
    +
    +
    +
    +
    Hash#set(key, value) → value
    +
      +
    • + key + (String) + – The key to use for this value. +
    • +
    • + value + (?) + – The value to use for this key. +
    • +
    + + +

    Stores value in the hash using the key key and returns value.

    + +
    Example
    + +
    var h = $H();
    +h.keys();
    +// -> [] (initially empty)
    +h.set('a', 'apple');
    +// -> "apple"
    +h.keys();
    +// -> ["a"] (has the new entry)
    +h.get('a');
    +// -> "apple"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/tojson/index.html b/doc/1.7_rc1/language/hash/prototype/tojson/index.html new file mode 100644 index 000000000..d5a350a24 --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/tojson/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toJSON() → Object
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/toobject/index.html b/doc/1.7_rc1/language/hash/prototype/toobject/index.html new file mode 100644 index 000000000..e44e8bb07 --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/toobject/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#toObject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toObject +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toObject() → Object
    + + +

    Returns a cloned, vanilla object whose properties (and property values) +match the keys (and values) from the hash.

    + +
    Example
    + +
    var h = new Hash({ a: 'apple', b: 'banana', c: 'coconut' });
    +var obj = h.toObject();
    +obj.a;
    +// -> "apple"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/toquerystring/index.html b/doc/1.7_rc1/language/hash/prototype/toquerystring/index.html new file mode 100644 index 000000000..6bd851642 --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/toquerystring/index.html @@ -0,0 +1,191 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#toQueryString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toQueryString +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toQueryString() → String
    + + +

    Returns a URL-encoded string containing the hash's contents as query +parameters according to the following rules:

    + +
      +
    • An undefined value results a parameter with no value portion at all +(simply the key name, no equal sign).
    • +
    • A null value results a parameter with a blank value (the key followed +by an equal sign and nothing else).
    • +
    • A boolean value results a parameter with the value "true" or "false".
    • +
    • An Array value results in a parameter for each array element, in +array order, each using the same key.
    • +
    • All keys and values are URI-encoded using JavaScript's native +encodeURIComponent function.
    • +
    + +

    The order of pairs in the string is not guaranteed, other than the order +of array values described above.

    + +
    Example
    + +
    $H({action: 'ship',
    +    order_id: 123,
    +    fees: ['f1', 'f2']
    +}).toQueryString();
    +// -> "action=ship&order_id=123&fees=f1&fees=f2"
    + $H({comment: '',
    +    'key with spaces': true,
    +    related_order: undefined,
    +    contents: null,
    +    'label': 'a demo'
    +}).toQueryString();
    +// -> "comment=&key%20with%20spaces=true&related_order&contents=&label=a%20demo"
    + // an empty hash is an empty query string:
    +$H().toQueryString();
    +// -> ""
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/totemplatereplacements/index.html b/doc/1.7_rc1/language/hash/prototype/totemplatereplacements/index.html new file mode 100644 index 000000000..dfbf88abb --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/totemplatereplacements/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#toTemplateReplacements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toTemplateReplacements +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toTemplateReplacements() → Object
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/unset/index.html b/doc/1.7_rc1/language/hash/prototype/unset/index.html new file mode 100644 index 000000000..78abb3506 --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/unset/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#unset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#unset +

    + + + + +
    +
    +
    +
    +
    +
    Hash#unset(key) → value
    + + +

    Deletes the stored pair for the given key from the hash and returns its +value.

    + +
    Example
    + +
    var h = new Hash({a: 'apple', b: 'banana', c: 'coconut'});
    +h.keys();
    +// -> ["a", "b", "c"]
    +h.unset('a');
    +// -> 'apple'
    +h.keys();
    +// -> ["b", "c"] ("a" is no longer in the hash)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/update/index.html b/doc/1.7_rc1/language/hash/prototype/update/index.html new file mode 100644 index 000000000..573ce267f --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/update/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#update + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#update +

    + + + + +
    +
    +
    +
    +
    +
    Hash#update(object) → Hash
    +
      +
    • + object + (Object | Hash) + – The object to merge with this hash to produce the resulting hash. +
    • +
    + + +

    Updates a hash in place with the key/value pairs of object, returns +the hash.

    + +

    Hash#update modifies the hash. To get a new hash instead, use +Hash#merge.

    + +
    Example
    + +
    var h = $H({one: "uno", two: "due"});
    +h.update({three: "tre"});
    +// -> h (a reference to the original hash)
    +h.keys();
    +// -> ["one", "two", "three"] (has merged contents)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/hash/prototype/values/index.html b/doc/1.7_rc1/language/hash/prototype/values/index.html new file mode 100644 index 000000000..c4d39657f --- /dev/null +++ b/doc/1.7_rc1/language/hash/prototype/values/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#values + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#values +

    + + + + +
    +
    +
    +
    +
    +
    Hash#values() → Array
    + + +

    Collects the values of the hash and returns them in an array.

    + +

    The order of the values is not guaranteed.

    + +
    Example
    + +
    var h = $H({one: "uno", two: "due", three: "tre"});
    +h.values();
    +// -> ["uno", "tre", "due"] (these may be in any order)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/index.html b/doc/1.7_rc1/language/index.html new file mode 100644 index 000000000..b6c744151 --- /dev/null +++ b/doc/1.7_rc1/language/index.html @@ -0,0 +1,229 @@ + + + + + Prototype v1.7_rc1 API documentation | Language section + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +

    + section Language section +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Additions to JavaScript's "standard library" and extensions to +built-in JavaScript objects.

    +
    +
    + + + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Try

      + +
    • +
    • +

      Prototype

      + +

      The Prototype namespace provides fundamental information about the +Prototype library you're using, as well as a central repository for default +iterators or functions.

      +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Array

      + +

      Prototype extends all native JavaScript arrays with quite a few powerful +methods.

      +
    • +
    • +

      Class

      + +

      Manages Prototype's class-based OOP system.

      +
    • +
    • +

      Date

      + +

      Extensions to the built-in Date object.

      +
    • +
    • +

      Function

      + +

      Extensions to the built-in Function object.

      +
    • +
    • +

      Hash

      + +

      A set of key/value pairs.

      +
    • +
    • +

      Number

      + +

      Extensions to the built-in Number object.

      +
    • +
    • +

      Object

      + +

      Extensions to the built-in Object object.

      +
    • +
    • +

      ObjectRange

      + +

      A succession of values.

      +
    • +
    • +

      PeriodicalExecuter

      + +

      Oversees the calling of a particular function periodically.

      +
    • +
    • +

      RegExp

      + +

      Extensions to the built-in RegExp object.

      +
    • +
    • +

      String

      + +

      Extensions to the built-in String class.

      +
    • +
    • +

      Template

      + +

      A class for sophisticated string interpolation.

      +
    • +
    +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/index.html b/doc/1.7_rc1/language/number/index.html new file mode 100644 index 000000000..18e5906eb --- /dev/null +++ b/doc/1.7_rc1/language/number/index.html @@ -0,0 +1,185 @@ + + + + + Prototype v1.7_rc1 API documentation | Number + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Number +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Number object.

    + +

    Prototype extends native JavaScript numbers in order to provide:

    + + +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/prototype/abs/index.html b/doc/1.7_rc1/language/number/prototype/abs/index.html new file mode 100644 index 000000000..7039b322d --- /dev/null +++ b/doc/1.7_rc1/language/number/prototype/abs/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#abs + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#abs +

    + + + + +
    +
    +
    +
    +
    +
    Number#abs() → Number
    + + +

    Returns the absolute value of the number. Convenience method that simply +calls Math.abs on this instance and returns the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/prototype/ceil/index.html b/doc/1.7_rc1/language/number/prototype/ceil/index.html new file mode 100644 index 000000000..007a6ddc4 --- /dev/null +++ b/doc/1.7_rc1/language/number/prototype/ceil/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#ceil + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#ceil +

    + + + + +
    +
    +
    +
    +
    +
    Number#ceil() → Number
    + + +

    Returns the smallest integer greater than or equal to the number. +Convenience method that simply calls Math.ceil on this instance and +returns the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/prototype/floor/index.html b/doc/1.7_rc1/language/number/prototype/floor/index.html new file mode 100644 index 000000000..be5e724bb --- /dev/null +++ b/doc/1.7_rc1/language/number/prototype/floor/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#floor + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#floor +

    + + + + +
    +
    +
    +
    +
    +
    Number#floor() → Number
    + + +

    Returns the largest integer less than or equal to the number. +Convenience method that simply calls Math.floor on this instance and +returns the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/prototype/round/index.html b/doc/1.7_rc1/language/number/prototype/round/index.html new file mode 100644 index 000000000..e3fc2733f --- /dev/null +++ b/doc/1.7_rc1/language/number/prototype/round/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#round + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#round +

    + + + + +
    +
    +
    +
    +
    +
    Number#round() → Number
    + + +

    Rounds the number to the nearest integer. Convenience method that simply +calls Math.round on this instance and returns the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/prototype/succ/index.html b/doc/1.7_rc1/language/number/prototype/succ/index.html new file mode 100644 index 000000000..c60e2d034 --- /dev/null +++ b/doc/1.7_rc1/language/number/prototype/succ/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#succ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#succ +

    + + + + +
    +
    +
    +
    +
    +
    Number#succ() → Number
    + + +

    Returns the successor of the current Number, as defined by current + 1. +Used to make numbers compatible with ObjectRange.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/prototype/times/index.html b/doc/1.7_rc1/language/number/prototype/times/index.html new file mode 100644 index 000000000..ce3923945 --- /dev/null +++ b/doc/1.7_rc1/language/number/prototype/times/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#times + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#times +

    + + + + +
    +
    +
    +
    +
    +
    Number#times(iterator[,context]) → Number
    +
      +
    • + iterator + (Function) + – An iterator function to call. +
    • +
    • + context + (Object) + – An optional context (this value) to use when calling iterator. +
    • +
    + + +

    Calls iterator the specified number of times, passing in a number as +the first parameter. The number will be 0 on first call, 1 on second +call, etc. times returns the number instance it was called on.

    + +
    Example
    + +
    (3).times(alert);
    +// -> Alerts "0", then "1", then "2"; returns 3
    + var obj = {count: 0, total: 0};
    +function add(addend) {
    +  ++this.count;
    +  this.total += addend;
    +}
    +(4).times(add, obj);
    +// -> 4
    +obj.count;
    +// -> 4
    +obj.total;
    +// -> 6 (e.g., 0 + 1 + 2 + 3)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/prototype/tocolorpart/index.html b/doc/1.7_rc1/language/number/prototype/tocolorpart/index.html new file mode 100644 index 000000000..a0ebcfed1 --- /dev/null +++ b/doc/1.7_rc1/language/number/prototype/tocolorpart/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#toColorPart + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#toColorPart +

    + + + + +
    +
    +
    +
    +
    +
    Number#toColorPart() → String
    + + +

    Produces a 2-digit hexadecimal representation of the number +(which is therefore assumed to be in the [0..255] range, inclusive). +Useful for composing CSS color strings.

    + +
    Example
    + +
    10.toColorPart()
    +// -> "0a"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/number/prototype/topaddedstring/index.html b/doc/1.7_rc1/language/number/prototype/topaddedstring/index.html new file mode 100644 index 000000000..8470de336 --- /dev/null +++ b/doc/1.7_rc1/language/number/prototype/topaddedstring/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#toPaddedString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#toPaddedString +

    + + + + +
    +
    +
    +
    +
    +
    Number#toPaddedString(length[, radix]) → String
    +
      +
    • + length + (Number) + – The minimum length for the resulting string. +
    • +
    • + radix + (Number) + – An optional radix for the string representation, defaults to 10 (decimal). +
    • +
    + + +

    Returns a string representation of the number padded with leading 0s so +that the string's length is at least equal to length. Takes an optional +radix argument which specifies the base to use for conversion.

    + +
    Examples
    + +
    (13).toPaddedString(4);
    +// -> "0013"
    + (13).toPaddedString(2);
    +// -> "13"
    + (13).toPaddedString(1);
    +// -> "13"
    + (13).toPaddedString(4, 16)
    +// -> "000d"
    + (13).toPaddedString(4, 2);
    +// -> "1101"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/clone/index.html b/doc/1.7_rc1/language/object/clone/index.html new file mode 100644 index 000000000..d27f0ef84 --- /dev/null +++ b/doc/1.7_rc1/language/object/clone/index.html @@ -0,0 +1,188 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.clone +

    + + + + +
    +
    +
    +
    +
    +
    Object.clone(object) → Object
    +
      +
    • + object + (Object) + – The object to clone. +
    • +
    + + +

    Creates and returns a shallow duplicate of the passed object by copying +all of the original's key/value pairs onto an empty object.

    + +

    Do note that this is a shallow copy, not a deep copy. Nested objects +will retain their references.

    + +
    Examples
    + +
    var original = {name: 'primaryColors', values: ['red', 'green', 'blue']};
    +var copy = Object.clone(original);
    + original.name;
    +// -> "primaryColors"
    +original.values[0];
    +// -> "red"
    +copy.name;
    +// -> "primaryColors"
    + copy.name = "secondaryColors";
    +original.name;
    +// -> "primaryColors"
    +copy.name;
    +// -> "secondaryColors"
    + copy.values[0] = 'magenta';
    +copy.values[1] = 'cyan';
    +copy.values[2] = 'yellow';
    +original.values[0];
    +// -> "magenta" (it's a shallow copy, so they share the array)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/extend/index.html b/doc/1.7_rc1/language/object/extend/index.html new file mode 100644 index 000000000..2bdc2e229 --- /dev/null +++ b/doc/1.7_rc1/language/object/extend/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.extend +

    + + + + +
    +
    +
    +
    +
    +
    Object.extend(destination, source) → Object
    +
      +
    • + destination + (Object) + – The object to receive the new properties. +
    • +
    • + source + (Object) + – The object whose properties will be duplicated. +
    • +
    + + +

    Copies all properties from the source to the destination object. Used by Prototype +to simulate inheritance (rather statically) by copying to prototypes.

    + +

    Documentation should soon become available that describes how Prototype implements +OOP, where you will find further details on how Prototype uses Object.extend and +Class.create (something that may well change in version 2.0). It will be linked +from here.

    + +

    Do not mistake this method with its quasi-namesake Element.extend, +which implements Prototype's (much more complex) DOM extension mechanism.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/index.html b/doc/1.7_rc1/language/object/index.html new file mode 100644 index 000000000..8f5a807cc --- /dev/null +++ b/doc/1.7_rc1/language/object/index.html @@ -0,0 +1,212 @@ + + + + + Prototype v1.7_rc1 API documentation | Object + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Object +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Object object.

    + +

    Because it is dangerous and invasive to augment Object.prototype (i.e., +add instance methods to objects), all these methods are static methods that +take an Object as their first parameter.

    + +

    Object is used by Prototype as a namespace; that is, it just keeps a few +new methods together, which are intended for namespaced access (i.e. starting +with "Object.").

    + +

    For the regular developer (who simply uses Prototype without tweaking it), the +most commonly used methods are probably Object.inspect and, to a lesser degree, +Object.clone.

    + +

    Advanced users, who wish to create their own objects like Prototype does, or +explore objects as if they were hashes, will turn to Object.extend, +Object.keys, and Object.values.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/inspect/index.html b/doc/1.7_rc1/language/object/inspect/index.html new file mode 100644 index 000000000..e21678949 --- /dev/null +++ b/doc/1.7_rc1/language/object/inspect/index.html @@ -0,0 +1,187 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.inspect +

    + + + + +
    +
    +
    +
    +
    +
    Object.inspect(obj) → String
    +
      +
    • + object + (Object) + – The item to be inspected. +
    • +
    + + +

    Returns the debug-oriented string representation of the object.

    + +
      +
    • undefined and null are represented as such.
    • +
    • Other types are looked up for a inspect method: if there is one, it is used, otherwise, +it reverts to the toString method.
    • +
    + +

    Prototype provides inspect methods for many types, both built-in and library-defined, +such as in String#inspect, Array#inspect, Enumerable#inspect and Hash#inspect, +which attempt to provide most-useful string representations (from a developer's standpoint) +for their respective types.

    + +
    Examples
    + +
    Object.inspect();
    +// -> 'undefined'
    + Object.inspect(null);
    +// -> 'null'
    + Object.inspect(false);
    +// -> 'false'
    + Object.inspect([1, 2, 3]);
    +// -> '[1, 2, 3]'
    + Object.inspect('hello');
    +// -> "'hello'"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/isarray/index.html b/doc/1.7_rc1/language/object/isarray/index.html new file mode 100644 index 000000000..8da7f0ed4 --- /dev/null +++ b/doc/1.7_rc1/language/object/isarray/index.html @@ -0,0 +1,172 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isArray +

    + + + + +
    +
    +
    +
    +
    +
    Object.isArray(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is an Array; false otherwise.

    + +
    Examples
    + +
    Object.isArray([]);
    +//-> true
    + Object.isArray($w());
    +//-> true
    + Object.isArray({ });
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/iselement/index.html b/doc/1.7_rc1/language/object/iselement/index.html new file mode 100644 index 000000000..a53aea319 --- /dev/null +++ b/doc/1.7_rc1/language/object/iselement/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isElement +

    + + + + +
    +
    +
    +
    +
    +
    Object.isElement(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is a DOM node of type 1; false otherwise.

    + +
    Examples
    + +
    Object.isElement(new Element('div'));
    +//-> true
    + Object.isElement(document.createElement('div'));
    +//-> true
    + Object.isElement($('id_of_an_exiting_element'));
    +//-> true
    + Object.isElement(document.createTextNode('foo'));
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/isfunction/index.html b/doc/1.7_rc1/language/object/isfunction/index.html new file mode 100644 index 000000000..95a70279b --- /dev/null +++ b/doc/1.7_rc1/language/object/isfunction/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isFunction + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isFunction +

    + + + + +
    +
    +
    +
    +
    +
    Object.isFunction(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type Function; false otherwise.

    + +
    Examples
    + +
    Object.isFunction($);
    +//-> true
    + Object.isFunction(123);
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/ishash/index.html b/doc/1.7_rc1/language/object/ishash/index.html new file mode 100644 index 000000000..cfd846065 --- /dev/null +++ b/doc/1.7_rc1/language/object/ishash/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isHash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isHash +

    + + + + +
    +
    +
    +
    +
    +
    Object.isHash(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is an instance of the Hash class; false +otherwise.

    + +
    Examples
    + +
    Object.isHash(new Hash({ }));
    +//-> true
    + Object.isHash($H({ }));
    +//-> true
    + Object.isHash({ });
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/isnumber/index.html b/doc/1.7_rc1/language/object/isnumber/index.html new file mode 100644 index 000000000..37f13be8e --- /dev/null +++ b/doc/1.7_rc1/language/object/isnumber/index.html @@ -0,0 +1,172 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isNumber + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isNumber +

    + + + + +
    +
    +
    +
    +
    +
    Object.isNumber(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type Number; false otherwise.

    + +
    Examples
    + +
    Object.isNumber(0);
    +//-> true
    + Object.isNumber(1.2);
    +//-> true
    + Object.isNumber("foo");
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/isstring/index.html b/doc/1.7_rc1/language/object/isstring/index.html new file mode 100644 index 000000000..1ef3c34db --- /dev/null +++ b/doc/1.7_rc1/language/object/isstring/index.html @@ -0,0 +1,172 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isString +

    + + + + +
    +
    +
    +
    +
    +
    Object.isString(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type String; false otherwise.

    + +
    Examples
    + +
    Object.isString("foo");
    +//-> true
    + Object.isString("");
    +//-> true
    + Object.isString(123);
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/isundefined/index.html b/doc/1.7_rc1/language/object/isundefined/index.html new file mode 100644 index 000000000..acaa0c533 --- /dev/null +++ b/doc/1.7_rc1/language/object/isundefined/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isUndefined + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isUndefined +

    + + + + +
    +
    +
    +
    +
    +
    Object.isUndefined(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type undefined; false otherwise.

    + +
    Examples
    + +
    Object.isUndefined();
    +//-> true
    + Object.isUndefined(undefined);
    +//-> true
    + Object.isUndefined(null);
    +//-> false
    + Object.isUndefined(0);
    +//-> false
    + Object.isUndefined("");
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/keys/index.html b/doc/1.7_rc1/language/object/keys/index.html new file mode 100644 index 000000000..dd71dfa0e --- /dev/null +++ b/doc/1.7_rc1/language/object/keys/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.keys + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.keys +

    + + + + +
    +
    +
    +
    +
    +
    Object.keys(object) → Array
    +
      +
    • + object + (Object) + – The object to pull keys from. +
    • +
    + + +

    Returns an array of the object's property names.

    + +

    Note that the order of the resulting array is browser-dependent — it +relies on the for...in loop, for which the ECMAScript spec does not +prescribe an enumeration order. Sort the resulting array if you wish to +normalize the order of the object keys.

    + +
    Examples
    + +
    Object.keys();
    +// -> []
    + Object.keys({ name: 'Prototype', version: '1.6.1' }).sort();
    +// -> ['name', 'version']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/tohtml/index.html b/doc/1.7_rc1/language/object/tohtml/index.html new file mode 100644 index 000000000..0f13445bf --- /dev/null +++ b/doc/1.7_rc1/language/object/tohtml/index.html @@ -0,0 +1,195 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.toHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toHTML +

    + + + + +
    +
    +
    +
    +
    +
    Object.toHTML(object) → String
    +
      +
    • + object + (Object) + – The object to convert to HTML. +
    • +
    + + +

    Converts the object to its HTML representation.

    + +

    Returns the return value of object's toHTML method if it exists; else +runs object through String.interpret.

    + +
    Examples
    + +
    var Bookmark = Class.create({
    +  initialize: function(name, url) {
    +    this.name = name;
    +    this.url = url;
    +  },
    +   toHTML: function() {
    +    return '<a href="#{url}">#{name}</a>'.interpolate(this);
    +  }
    +});
    + var api = new Bookmark('Prototype API', 'http://prototypejs.org/api');
    + Object.toHTML(api);
    +//-> '<a href="http://prototypejs.org/api">Prototype API</a>'
    + Object.toHTML("Hello world!");
    +//-> "Hello world!"
    + Object.toHTML();
    +//-> ""
    + Object.toHTML(null);
    +//-> ""
    + Object.toHTML(undefined);
    +//-> ""
    + Object.toHTML(true);
    +//-> "true"
    + Object.toHTML(false);
    +//-> "false"
    + Object.toHTML(123);
    +//-> "123"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/tojson/index.html b/doc/1.7_rc1/language/object/tojson/index.html new file mode 100644 index 000000000..159f39b88 --- /dev/null +++ b/doc/1.7_rc1/language/object/tojson/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Object.toJSON(object) → String
    +
      +
    • + object + (Object) + – The object to be serialized. +
    • +
    + + +

    Returns a JSON string.

    + +

    undefined and function types have no JSON representation. boolean +and null are coerced to strings.

    + +

    For other types, Object.toJSON looks for a toJSON method on object. +If there is one, it is used; otherwise the object is treated like a +generic Object.

    + +

    For more information on Prototype's JSON encoder, hop to our +tutorial.

    + +
    Example
    + +
    var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']};
    +Object.toJSON(data);
    +//-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/toquerystring/index.html b/doc/1.7_rc1/language/object/toquerystring/index.html new file mode 100644 index 000000000..c8de07e18 --- /dev/null +++ b/doc/1.7_rc1/language/object/toquerystring/index.html @@ -0,0 +1,181 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.toQueryString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toQueryString +

    + + + + +
    +
    +
    +
    +
    +
    Object.toQueryString(object) → String
    +
      +
    • + object + (Object) + – The object whose property/value pairs will be converted. +
    • +
    + + +

    Turns an object into its URL-encoded query string representation.

    + +

    This is a form of serialization, and is mostly useful to provide complex +parameter sets for stuff such as objects in the Ajax namespace (e.g. +Ajax.Request).

    + +

    Undefined-value pairs will be serialized as if empty-valued. Array-valued +pairs will get serialized with one name/value pair per array element. All +values get URI-encoded using JavaScript's native encodeURIComponent +function.

    + +

    The order of pairs in the serialized form is not guaranteed (and mostly +irrelevant anyway) — except for array-based parts, which are serialized +in array order.

    + +
    Examples
    + +
    Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })
    +// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/object/values/index.html b/doc/1.7_rc1/language/object/values/index.html new file mode 100644 index 000000000..7cc1c80ac --- /dev/null +++ b/doc/1.7_rc1/language/object/values/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.values + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.values +

    + + + + +
    +
    +
    +
    +
    +
    Object.values(object) → Array
    +
      +
    • + object + (Object) + – The object to pull values from. +
    • +
    + + +

    Returns an array of the object's property values.

    + +

    Note that the order of the resulting array is browser-dependent — it +relies on the for...in loop, for which the ECMAScript spec does not +prescribe an enumeration order.

    + +

    Also, remember that while property names are unique, property values +have no such constraint.

    + +
    Examples
    + +
    Object.values();
    +// -> []
    + Object.values({ name: 'Prototype', version: '1.6.1' }).sort();
    +// -> ['1.6.1', 'Prototype']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/objectrange/index.html b/doc/1.7_rc1/language/objectrange/index.html new file mode 100644 index 000000000..5586ce04d --- /dev/null +++ b/doc/1.7_rc1/language/objectrange/index.html @@ -0,0 +1,199 @@ + + + + + Prototype v1.7_rc1 API documentation | ObjectRange + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class ObjectRange +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A succession of values.

    + +

    An ObjectRange can model a range of any value that implements a succ +method (which links that value to its "successor").

    + +

    Prototype provides such a method for Number and String, but you +are (of course) welcome to implement useful semantics in your own objects, +in order to enable ranges based on them.

    + +

    ObjectRange mixes in Enumerable, which makes ranges very versatile. +It takes care, however, to override the default code for include, to +achieve better efficiency.

    + +

    While ObjectRange does provide a constructor, the preferred way to obtain +a range is to use the $R utility function, which is strictly equivalent +(only way more concise to use).

    + +

    See $R for more information.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance properties

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/objectrange/new/index.html b/doc/1.7_rc1/language/objectrange/new/index.html new file mode 100644 index 000000000..1d2a34525 --- /dev/null +++ b/doc/1.7_rc1/language/objectrange/new/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | new ObjectRange + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new ObjectRange +

    + + + + +
    +
    +
    +
    +
    +
    new(start, end[, exclusive = false])
    + + +

    Creates a new ObjectRange.

    + +

    The exclusive argument specifies whether end itself is a part of the +range.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/objectrange/prototype/end/index.html b/doc/1.7_rc1/language/objectrange/prototype/end/index.html new file mode 100644 index 000000000..00beb1af3 --- /dev/null +++ b/doc/1.7_rc1/language/objectrange/prototype/end/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | ObjectRange#end + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property ObjectRange#end +

    + + + + +
    +
    +
    +
    +
    +
    ObjectRange#end → ?
    + + +

    The upper bounding value of the range.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/objectrange/prototype/include/index.html b/doc/1.7_rc1/language/objectrange/prototype/include/index.html new file mode 100644 index 000000000..004c5ac4c --- /dev/null +++ b/doc/1.7_rc1/language/objectrange/prototype/include/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.7_rc1 API documentation | ObjectRange#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method ObjectRange#include +

    + + + + +
    +
    +
    +
    +
    +
    ObjectRange#include(value) → Boolean
    + + +

    Determines whether the value is included in the range.

    + +

    This assumes the values in the range have a valid strict weak ordering +(have valid semantics for the < operator). While ObjectRange mixes +in Enumerable, this method overrides the default version of +Enumerable#include, and is much more efficient (it uses a maximum of +two comparisons).

    + +
    Examples
    + +
    $R(1, 10).include(5);
    +// -> true
    + $R('a', 'h').include('x');
    +// -> false
    + $R(1, 10).include(10);
    +// -> true
    + $R(1, 10, true).include(10);
    +// -> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/objectrange/prototype/start/index.html b/doc/1.7_rc1/language/objectrange/prototype/start/index.html new file mode 100644 index 000000000..c04f787a1 --- /dev/null +++ b/doc/1.7_rc1/language/objectrange/prototype/start/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | ObjectRange#start + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property ObjectRange#start +

    + + + + +
    +
    +
    +
    +
    +
    ObjectRange#start → ?
    + + +

    The lower bounding value of the range.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/periodicalexecuter/index.html b/doc/1.7_rc1/language/periodicalexecuter/index.html new file mode 100644 index 000000000..2cb69893a --- /dev/null +++ b/doc/1.7_rc1/language/periodicalexecuter/index.html @@ -0,0 +1,183 @@ + + + + + Prototype v1.7_rc1 API documentation | PeriodicalExecuter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class PeriodicalExecuter +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Oversees the calling of a particular function periodically.

    + +

    PeriodicalExecuter shields you from multiple parallel executions of a +callback function, should it take longer than the given interval to +execute.

    + +

    This is especially useful if you use one to interact with the user at +given intervals (e.g. use a prompt or confirm call): this will avoid +multiple message boxes all waiting to be actioned.

    + +
    Example
    + +
    new PeriodicalExecuter(function(pe) {
    +  if (!confirm('Want me to annoy you again later?')) {
    +    pe.stop();
    +  }
    +}, 5);
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/periodicalexecuter/new/index.html b/doc/1.7_rc1/language/periodicalexecuter/new/index.html new file mode 100644 index 000000000..c91d38a36 --- /dev/null +++ b/doc/1.7_rc1/language/periodicalexecuter/new/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | new PeriodicalExecuter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new PeriodicalExecuter +

    + + + + +
    +
    +
    +
    +
    +
    new(callback, frequency)
    +
      +
    • + callback + (Function) + – the function to be executed at each interval. +
    • +
    • + frequency + (Number) + – the amount of time, in seconds, to wait in between callbacks. +
    • +
    + + +

    Creates a PeriodicalExecuter.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/periodicalexecuter/prototype/stop/index.html b/doc/1.7_rc1/language/periodicalexecuter/prototype/stop/index.html new file mode 100644 index 000000000..03848a03a --- /dev/null +++ b/doc/1.7_rc1/language/periodicalexecuter/prototype/stop/index.html @@ -0,0 +1,160 @@ + + + + + Prototype v1.7_rc1 API documentation | PeriodicalExecuter#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method PeriodicalExecuter#stop +

    + + + + +
    +
    +
    +
    +
    +
    PeriodicalExecuter#stop() → undefined
    + + +

    Stops the periodical executer (there will be no further triggers).

    + +

    Once a PeriodicalExecuter is created, it constitues an infinite loop, +triggering at the given interval until the page unloads. This method lets +you stop it any time you want.

    + +
    Example
    + +

    This will only alert 1, 2 and 3, then the PeriodicalExecuter stops.

    + +
    var count = 0;
    +new PeriodicalExecuter(function(pe) {
    +  if (++count > 3) {
    +    pe.stop();
    +  } else {
    +    alert(count);
    +  }
    +}, 1);
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/browser/index.html b/doc/1.7_rc1/language/prototype/browser/index.html new file mode 100644 index 000000000..12f8d9c2b --- /dev/null +++ b/doc/1.7_rc1/language/prototype/browser/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Browser + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Prototype.Browser +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A collection of Boolean values indicating the browser which is +currently in use. Available properties are IE, Opera, WebKit, +MobileSafari and Gecko.

    + +

    Example

    + +
    Prototype.Browser.WebKit;
    +//-> true, when executed in any WebKit-based browser.
    +
    +
    +
    +
    + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/browserfeatures/elementextensions/index.html b/doc/1.7_rc1/language/prototype/browserfeatures/elementextensions/index.html new file mode 100644 index 000000000..b566f4910 --- /dev/null +++ b/doc/1.7_rc1/language/prototype/browserfeatures/elementextensions/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.BrowserFeatures.ElementExtensions + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Prototype.BrowserFeatures.ElementExtensions +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.BrowserFeatures.ElementExtensions → Boolean
    + + +

    Used internally to detect if the browser supports extending html element +prototypes.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/browserfeatures/index.html b/doc/1.7_rc1/language/prototype/browserfeatures/index.html new file mode 100644 index 000000000..d8b49b9da --- /dev/null +++ b/doc/1.7_rc1/language/prototype/browserfeatures/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.BrowserFeatures + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Prototype.BrowserFeatures +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A collection of Boolean values indicating the presence of specific +browser features.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class properties

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/browserfeatures/selectorsapi/index.html b/doc/1.7_rc1/language/prototype/browserfeatures/selectorsapi/index.html new file mode 100644 index 000000000..45f30eb41 --- /dev/null +++ b/doc/1.7_rc1/language/prototype/browserfeatures/selectorsapi/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.BrowserFeatures.SelectorsAPI + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Prototype.BrowserFeatures.SelectorsAPI +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.BrowserFeatures.SelectorsAPI → Boolean
    + + +

    Used internally to detect if the browser supports the +NodeSelector API.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/browserfeatures/xpath/index.html b/doc/1.7_rc1/language/prototype/browserfeatures/xpath/index.html new file mode 100644 index 000000000..ab1d2c14c --- /dev/null +++ b/doc/1.7_rc1/language/prototype/browserfeatures/xpath/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.BrowserFeatures.XPath + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Prototype.BrowserFeatures.XPath +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.BrowserFeatures.XPath → Boolean
    + + +

    Used internally to detect if the browser supports +DOM Level 3 XPath.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/emptyfunction/index.html b/doc/1.7_rc1/language/prototype/emptyfunction/index.html new file mode 100644 index 000000000..342645597 --- /dev/null +++ b/doc/1.7_rc1/language/prototype/emptyfunction/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.emptyFunction + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.emptyFunction +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.emptyFunction([argument...]) → undefined
    +
      +
    • + argument + (Object) + – Optional arguments +
    • +
    + + +

    The Prototype.emptyFunction does nothing... and returns nothing!

    + +

    It is used thoughout the framework to provide a fallback function in order +to cut down on conditionals. Typically you'll find it as a default value +for optional callback functions.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/index.html b/doc/1.7_rc1/language/prototype/index.html new file mode 100644 index 000000000..9ae145e96 --- /dev/null +++ b/doc/1.7_rc1/language/prototype/index.html @@ -0,0 +1,240 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Prototype +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    The Prototype namespace provides fundamental information about the +Prototype library you're using, as well as a central repository for default +iterators or functions.

    + +

    We say "namespace," because the Prototype object is not intended for +instantiation, nor for mixing in other objects. It's really just... a +namespace.

    + +
    Your version of Prototype
    + +

    Your scripts can check against a particular version of Prototype by +examining Prototype.Version, which is a version String (e.g. +"<%= PROTOTYPE_VERSION %>"). The famous +script.aculo.us library does this at load time to +ensure it's being used with a reasonably recent version of Prototype, for +instance.

    + +
    Browser features
    + +

    Prototype also provides a (nascent) repository of +browser feature information, which it then +uses here and there in its source code. The idea is, first, to make +Prototype's source code more readable; and second, to centralize whatever +scripting trickery might be necessary to detect the browser feature, in +order to ease maintenance.

    + +
    Default iterators and functions
    + +

    Numerous methods in Prototype objects (most notably the Enumerable +module) let the user pass in a custom iterator, but make it optional by +defaulting to an "identity function" (an iterator that just returns its +argument, untouched). This is the Prototype.K function, which you'll +see referred to in many places.

    + +

    Many methods also take it easy by protecting themselves against missing +methods here and there, reverting to empty functions when a supposedly +available method is missing. Such a function simply ignores its potential +arguments, and does nothing whatsoever (which is, oddly enough, +blazing fast). The quintessential empty function sits, unsurprisingly, +at Prototype.emptyFunction (note the lowercase first letter).

    +
    +
    + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Prototype.Selector

      + +

      A namespace that acts as a wrapper around +the choosen selector engine (Sizzle by default).

      +
    • +
    • +

      Prototype.Browser

      + +

      A collection of Boolean values indicating the browser which is +currently in use. Available properties are IE, Opera, WebKit, +MobileSafari and Gecko.

      +
    • +
    • +

      Prototype.BrowserFeatures

      + +

      A collection of Boolean values indicating the presence of specific +browser features.

      +
    • +
    +
    +
    + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Class properties

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/k/index.html b/doc/1.7_rc1/language/prototype/k/index.html new file mode 100644 index 000000000..f4869386c --- /dev/null +++ b/doc/1.7_rc1/language/prototype/k/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.K + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.K +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.K(argument) → argument
    +
      +
    • + argument + (Object) + – Optional argument... +
    • +
    + + +

    Prototype.K is Prototype's very own +identity function, i.e. +it returns its argument untouched.

    + +

    This is used throughout the framework, most notably in the Enumerable +module as a default value for iterators.

    + +
    Examples
    + +
    Prototype.K('hello world!');
    +// -> 'hello world!'
    + Prototype.K(200);
    +// -> 200
    + Prototype.K(Prototype.K);
    +// -> Prototype.K
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/selector/find/index.html b/doc/1.7_rc1/language/prototype/selector/find/index.html new file mode 100644 index 000000000..28c001a2c --- /dev/null +++ b/doc/1.7_rc1/language/prototype/selector/find/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Selector.find + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.Selector.find +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.Selector.find(elements, expression[, index = 0]) → Element
    +
      +
    • + elements + (Enumerable) + – a collection of DOM elements. +
    • +
    • + expression + (String) + – A CSS selector. +
    • +
    • + index + – Numeric index of the match to return, defaults to 0. +
    • +
    + + +

    Filters the given collection of elements with expression and returns the +first matching element (or the indexth matching element if index is +specified).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/selector/index.html b/doc/1.7_rc1/language/prototype/selector/index.html new file mode 100644 index 000000000..0e2485233 --- /dev/null +++ b/doc/1.7_rc1/language/prototype/selector/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Selector + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Prototype.Selector +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A namespace that acts as a wrapper around +the choosen selector engine (Sizzle by default).

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/selector/match/index.html b/doc/1.7_rc1/language/prototype/selector/match/index.html new file mode 100644 index 000000000..da55b9221 --- /dev/null +++ b/doc/1.7_rc1/language/prototype/selector/match/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Selector.match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.Selector.match +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.Selector.match(element, expression) → Boolean
    +
      +
    • + element + (Element) + – a DOM element. +
    • +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Tests whether element matches the CSS selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/selector/select/index.html b/doc/1.7_rc1/language/prototype/selector/select/index.html new file mode 100644 index 000000000..29e561974 --- /dev/null +++ b/doc/1.7_rc1/language/prototype/selector/select/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Selector.select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.Selector.select +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.Selector.select(expression[, root = document]) → [Element…]
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    • + root + (Element | document) + – A "scope" to search within. All results will be descendants of this node. +
    • +
    + + +

    Searches root for elements that match the provided CSS selector and returns an +array of extended Element objects.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/prototype/version/index.html b/doc/1.7_rc1/language/prototype/version/index.html new file mode 100644 index 000000000..8e2d79da9 --- /dev/null +++ b/doc/1.7_rc1/language/prototype/version/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Version + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Prototype.Version +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.Version → String
    + + +

    The version of the Prototype library you are using (e.g. +"<%= PROTOTYPE_VERSION %>").

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/regexp/escape/index.html b/doc/1.7_rc1/language/regexp/escape/index.html new file mode 100644 index 000000000..d6e95cfb7 --- /dev/null +++ b/doc/1.7_rc1/language/regexp/escape/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.7_rc1 API documentation | RegExp.escape + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method RegExp.escape +

    + + + + +
    +
    +
    +
    +
    +
    RegExp.escape(str) → String
    +
      +
    • + str + (String) + – A string intended to be used in a RegExp constructor. +
    • +
    + + +

    Escapes any characters in the string that have special meaning in a +regular expression.

    + +

    Use before passing a string into the RegExp constructor.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/regexp/index.html b/doc/1.7_rc1/language/regexp/index.html new file mode 100644 index 000000000..969e1907a --- /dev/null +++ b/doc/1.7_rc1/language/regexp/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.7_rc1 API documentation | RegExp + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class RegExp +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in RegExp object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/regexp/prototype/match/index.html b/doc/1.7_rc1/language/regexp/prototype/match/index.html new file mode 100644 index 000000000..56a20f005 --- /dev/null +++ b/doc/1.7_rc1/language/regexp/prototype/match/index.html @@ -0,0 +1,141 @@ + + + + + Prototype v1.7_rc1 API documentation | RegExp#match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method RegExp#match +

    + + + + +
    +
    +
    +
    +
    +
    RegExp#match(str) → Boolean
    + + +

    Return true if string matches the regular expression, false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/index.html b/doc/1.7_rc1/language/string/index.html new file mode 100644 index 000000000..036b40349 --- /dev/null +++ b/doc/1.7_rc1/language/string/index.html @@ -0,0 +1,261 @@ + + + + + Prototype v1.7_rc1 API documentation | String + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class String +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in String class.

    + +

    Prototype enhances the String object with a series of useful methods for +ranging from the trivial to the complex. Tired of stripping trailing +whitespace? Try String#strip. Want to replace replace? Have a look at +String#sub and String#gsub. Need to parse a query string? We have +what you need.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/interpret/index.html b/doc/1.7_rc1/language/string/interpret/index.html new file mode 100644 index 000000000..0840f2281 --- /dev/null +++ b/doc/1.7_rc1/language/string/interpret/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | String.interpret + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method String.interpret +

    + + + + +
    +
    +
    +
    +
    +
    String.interpret(value) → String
    + + +

    Coerces value into a string. Returns an empty string for null.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/blank/index.html b/doc/1.7_rc1/language/string/prototype/blank/index.html new file mode 100644 index 000000000..ca686a49b --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/blank/index.html @@ -0,0 +1,182 @@ + + + + + Prototype v1.7_rc1 API documentation | String#blank + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#blank +

    + + + + +
    +
    +
    +
    +
    +
    String#blank() → Boolean
    + + +

    Check if the string is "blank" — either empty (length of 0) or +containing only whitespace.

    + +
    Example
    + +
    ''.blank();
    +//-> true
    + '  '.blank();
    +//-> true
    + ' a '.blank();
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/camelize/index.html b/doc/1.7_rc1/language/string/prototype/camelize/index.html new file mode 100644 index 000000000..fd61d74ab --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/camelize/index.html @@ -0,0 +1,183 @@ + + + + + Prototype v1.7_rc1 API documentation | String#camelize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#camelize +

    + + + + +
    +
    +
    +
    +
    +
    String#camelize() → String
    + + +

    Converts a string separated by dashes into a camelCase equivalent. For +instance, 'foo-bar' would be converted to 'fooBar'.

    + +

    Prototype uses this internally for translating CSS properties into their +DOM style property equivalents.

    + +
    Examples
    + +
    'background-color'.camelize();
    +// -> 'backgroundColor'
    + '-moz-binding'.camelize();
    +// -> 'MozBinding'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/capitalize/index.html b/doc/1.7_rc1/language/string/prototype/capitalize/index.html new file mode 100644 index 000000000..35aa28c83 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/capitalize/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | String#capitalize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#capitalize +

    + + + + +
    +
    +
    +
    +
    +
    String#capitalize() → String
    + + +

    Capitalizes the first letter of a string and downcases all the others.

    + +
    Examples
    + +
    'hello'.capitalize();
    +// -> 'Hello'
    + 'HELLO WORLD!'.capitalize();
    +// -> 'Hello world!'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/dasherize/index.html b/doc/1.7_rc1/language/string/prototype/dasherize/index.html new file mode 100644 index 000000000..a56a10d84 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/dasherize/index.html @@ -0,0 +1,187 @@ + + + + + Prototype v1.7_rc1 API documentation | String#dasherize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#dasherize +

    + + + + +
    +
    +
    +
    +
    +
    String#dasherize() → String
    + + +

    Replaces every instance of the underscore character "_" by a dash "-".

    + +
    Example
    + +
    'border_bottom_width'.dasherize();
    +// -> 'border-bottom-width'
    +
    +
    + +
    Note
    + +

    Used in conjunction with String#underscore, String#dasherize +converts a DOM style into its CSS equivalent.

    + +
    'borderBottomWidth'.underscore().dasherize();
    +// -> 'border-bottom-width'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/empty/index.html b/doc/1.7_rc1/language/string/prototype/empty/index.html new file mode 100644 index 000000000..6a46a82b6 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/empty/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | String#empty + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#empty +

    + + + + +
    +
    +
    +
    +
    +
    String#empty() → Boolean
    + + +

    Checks if the string is empty.

    + +
    Example
    + +
    ''.empty();
    +//-> true
    + '  '.empty();
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/endswith/index.html b/doc/1.7_rc1/language/string/prototype/endswith/index.html new file mode 100644 index 000000000..59865e2a7 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/endswith/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#endsWith + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#endsWith +

    + + + + +
    +
    +
    +
    +
    +
    String#endsWith(substring) → Boolean
    + + +

    Checks if the string ends with substring.

    + +
    Example
    + +
    'slaughter'.endsWith('laughter')
    +// -> true
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/escapehtml/index.html b/doc/1.7_rc1/language/string/prototype/escapehtml/index.html new file mode 100644 index 000000000..43dc6a56c --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/escapehtml/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#escapeHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#escapeHTML +

    + + + + +
    +
    +
    +
    +
    +
    String#escapeHTML() → String
    + + +

    Converts HTML special characters to their entity equivalents.

    + +
    Example
    + +
    '<div class="article">This is an article</div>'.escapeHTML();
    +// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/evaljson/index.html b/doc/1.7_rc1/language/string/prototype/evaljson/index.html new file mode 100644 index 000000000..5f5d3cc41 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/evaljson/index.html @@ -0,0 +1,201 @@ + + + + + Prototype v1.7_rc1 API documentation | String#evalJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#evalJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#evalJSON([sanitize = false]) → object
    + + +

    Evaluates the JSON in the string and returns the resulting object.

    + +

    If the optional sanitize parameter is set to true, the string is +checked for possible malicious attempts; if one is detected, eval +is not called.

    + +
    Warning
    + +

    If the JSON string is not well formated or if a malicious attempt is +detected a SyntaxError is thrown.

    + +
    Examples
    + +
    var person = '{ "name": "Violet", "occupation": "character" }'.evalJSON();
    +person.name;
    +//-> "Violet"
    + person = 'grabUserPassword()'.evalJSON(true);
    +//-> SyntaxError: Badly formed JSON string: 'grabUserPassword()'
    + person = '/*-secure-\n{"name": "Violet", "occupation": "character"}\n*\/'.evalJSON()
    +person.name;
    +//-> "Violet"
    +
    +
    + +
    Note
    + +

    Always set the sanitize parameter to true for data coming from +externals sources to prevent XSS attacks.

    + +

    As String#evalJSON internally calls String#unfilterJSON, optional +security comment delimiters (defined in Prototype.JSONFilter) are +automatically removed.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/evalscripts/index.html b/doc/1.7_rc1/language/string/prototype/evalscripts/index.html new file mode 100644 index 000000000..2c6f47d08 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/evalscripts/index.html @@ -0,0 +1,220 @@ + + + + + Prototype v1.7_rc1 API documentation | String#evalScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#evalScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#evalScripts() → Array
    + + +

    Evaluates the content of any inline <script> block present in the string. +Returns an array containing the value returned by each script. +<script> blocks referencing external files will be treated as though +they were empty (the result for that position in the array will be undefined); +external files are not loaded and processed by String#evalScripts.

    + +
    Examples
    + +
    'lorem... <script>2 + 2</script>'.evalScripts();
    +// -> [4]
    + '<script>2 + 2<script><script>alert("hello world!")</script>'.evalScripts();
    +// -> [4, undefined] (and displays 'hello world!' in the alert dialog)
    +
    +
    + +
    About evalScripts, vars, and defining functions
    + +

    String#evalScripts evaluates script blocks, but this does not mean +they are evaluated in the global scope. They aren't, they're evaluated in +the scope of the String#evalScripts method. This has important +ramifications for your scripts:

    + +
      +
    • Anything in your script declared with the var keyword will be +discarded momentarily after evaluation, and will be invisible to any +other scope.
    • +
    • If any <script> blocks define functions, they will need to be +assigned to properties of the window object.
    • +
    + +

    For example, this won't work:

    + +
    // This kind of script won't work if processed by evalScripts:
    +function coolFunc() {
    +  // Amazing stuff!
    +}
    +
    +
    + +

    Instead, use the following syntax:

    + +
    // This kind of script WILL work if processed by evalScripts:
    +window.coolFunc = function() {
    +  // Amazing stuff!
    +}
    +
    +
    + +

    (You can leave off the window. part of that, but it's bad form.) +Evaluates the content of any script block present in the string. Returns +an array containing the value returned by each script.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/extractscripts/index.html b/doc/1.7_rc1/language/string/prototype/extractscripts/index.html new file mode 100644 index 000000000..2b2791c99 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/extractscripts/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | String#extractScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#extractScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#extractScripts() → Array
    + + +

    Extracts the content of any <script> blocks present in the string and +returns them as an array of strings.

    + +

    This method is used internally by String#evalScripts. It does not +evaluate the scripts (use String#evalScripts to do that), but can be +usefull if you need to evaluate the scripts at a later date.

    + +
    Examples
    + +
    'lorem... <script>2 + 2</script>'.extractScripts();
    +// -> ['2 + 2']
    + '<script>2 + 2</script><script>alert("hello world!")</script>'.extractScripts();
    +// -> ['2 + 2', 'alert("hello world!")']
    +
    +
    + +
    Notes
    + +

    To evaluate the scripts later on, you can use the following:

    + +
    var myScripts = '<script>2 + 2</script><script>alert("hello world!")</script>'.extractScripts();
    +// -> ['2 + 2', 'alert("hello world!")']
    + var myReturnedValues = myScripts.map(function(script) {
    +  return eval(script);
    +});
    +// -> [4, undefined] (and displays 'hello world!' in the alert dialog)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/gsub/index.html b/doc/1.7_rc1/language/string/prototype/gsub/index.html new file mode 100644 index 000000000..1a7e01eb1 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/gsub/index.html @@ -0,0 +1,215 @@ + + + + + Prototype v1.7_rc1 API documentation | String#gsub + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#gsub +

    + + + + +
    +
    +
    +
    +
    +
    String#gsub(pattern, replacement) → String
    + + +

    Returns the string with every occurence of a given pattern replaced by either a +regular string, the returned value of a function or a Template string. +The pattern can be a string or a regular expression.

    + +

    If its second argument is a string String#gsub works just like the native JavaScript +method replace() set to global match.

    + +
    var mouseEvents = 'click dblclick mousedown mouseup mouseover mousemove mouseout';
    + mouseEvents.gsub(' ', ', ');
    +// -> 'click, dblclick, mousedown, mouseup, mouseover, mousemove, mouseout'
    + mouseEvents.gsub(/\s+/, ', ');
    +// -> 'click, dblclick, mousedown, mouseup, mouseover, mousemove, mouseout'
    +
    +
    + +

    If you pass it a function, it will be invoked for every occurrence of the pattern +with the match of the current pattern as its unique argument. Note that this argument +is the returned value of the match() method called on the current pattern. It is +in the form of an array where the first element is the entire match and every subsequent +one corresponds to a parenthesis group in the regex.

    + +
    mouseEvents.gsub(/\w+/, function(match){ return 'on' + match[0].capitalize() });
    +// -> 'onClick onDblclick onMousedown onMouseup onMouseover onMousemove onMouseout'
    + var markdown = '![a pear](/img/pear.jpg) ![an orange](/img/orange.jpg)';
    + markdown.gsub(/!\[(.*?)\]\((.*?)\)/, function(match) {
    +  return '<img alt="' + match[1] + '" src="' + match[2] + '" />';
    +});
    +// -> '<img alt="a pear" src="/img/pear.jpg" /> <img alt="an orange" src="/img/orange.jpg" />'
    +
    +
    + +

    Lastly, you can pass String#gsub a Template string in which you can also access +the returned value of the match() method using the ruby inspired notation: #{0} +for the first element of the array, #{1} for the second one, and so on. +So our last example could be easily re-written as:

    + +
    markdown.gsub(/!\[(.*?)\]\((.*?)\)/, '<img alt="#{1}" src="#{2}" />');
    +// -> '<img alt="a pear" src="/img/pear.jpg" /> <img alt="an orange" src="/img/orange.jpg" />'
    +
    +
    + +

    If you need an equivalent to String#gsub but without global match set on, try String#sub.

    + +
    Note
    + +

    Do not use the "g" flag on the regex as this will create an infinite loop.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/include/index.html b/doc/1.7_rc1/language/string/prototype/include/index.html new file mode 100644 index 000000000..db7b6cfee --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/include/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | String#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#include +

    + + + + +
    +
    +
    +
    +
    +
    String#include(substring) → Boolean
    + + +

    Checks if the string contains substring.

    + +
    Example
    + +
    'Prototype framework'.include('frame');
    +//-> true
    +'Prototype framework'.include('frameset');
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/inspect/index.html b/doc/1.7_rc1/language/string/prototype/inspect/index.html new file mode 100644 index 000000000..cf2eec702 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/inspect/index.html @@ -0,0 +1,184 @@ + + + + + Prototype v1.7_rc1 API documentation | String#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#inspect +

    + + + + +
    +
    +
    +
    +
    +
    String#inspect([useDoubleQuotes = false]) → String
    + + +

    Returns a debug-oriented version of the string (i.e. wrapped in single or +double quotes, with backslashes and quotes escaped).

    + +

    For more information on inspect methods, see Object.inspect.

    + +

    Examples

    + +
    'I\'m so happy.'.inspect();
    +// -> '\'I\\\'m so happy.\''
    +// (displayed as 'I\'m so happy.' in an alert dialog or the console)
    + 'I\'m so happy.'.inspect(true);
    +// -> '"I'm so happy."'
    +// (displayed as "I'm so happy." in an alert dialog or the console)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/interpolate/index.html b/doc/1.7_rc1/language/string/prototype/interpolate/index.html new file mode 100644 index 000000000..53c438d45 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/interpolate/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | String#interpolate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#interpolate +

    + + + + +
    +
    +
    +
    +
    +
    String#interpolate(object[, pattern]) → String
    + + +

    Treats the string as a Template and fills it with object's +properties.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/isjson/index.html b/doc/1.7_rc1/language/string/prototype/isjson/index.html new file mode 100644 index 000000000..5c228582e --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/isjson/index.html @@ -0,0 +1,184 @@ + + + + + Prototype v1.7_rc1 API documentation | String#isJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#isJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#isJSON() → Boolean
    + + +

    Check if the string is valid JSON by the use of regular expressions. +This security method is called internally.

    + +
    Examples
    + +
    "something".isJSON();
    +// -> false
    +"\"something\"".isJSON();
    +// -> true
    +"{ foo: 42 }".isJSON();
    +// -> false
    +"{ \"foo\": 42 }".isJSON();
    +// -> true
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/parsequery/index.html b/doc/1.7_rc1/language/string/prototype/parsequery/index.html new file mode 100644 index 000000000..effae03d5 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/parsequery/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | String#parseQuery + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#parseQuery +

    + + + + +
    +
    +
    +
    +
    +
    String#parseQuery([separator = '&']) → Object
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/scan/index.html b/doc/1.7_rc1/language/string/prototype/scan/index.html new file mode 100644 index 000000000..ddc6f4b82 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/scan/index.html @@ -0,0 +1,201 @@ + + + + + Prototype v1.7_rc1 API documentation | String#scan + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#scan +

    + + + + +
    +
    +
    +
    +
    +
    String#scan(pattern, iterator) → String
    + + +

    Allows iterating over every occurrence of the given pattern (which can be a +string or a regular expression). +Returns the original string.

    + +

    Internally just calls String#gsub passing it pattern and iterator as arguments.

    + +
    Examples
    + +
    'apple, pear & orange'.scan(/\w+/, alert);
    +// -> 'apple pear orange' (and displays 'apple', 'pear' and 'orange' in three successive alert dialogs)
    +
    +
    + +

    Can be used to populate an array:

    + +
    var fruits = [];
    +'apple, pear & orange'.scan(/\w+/, function(match) { fruits.push(match[0]) });
    +fruits.inspect()
    +// -> ['apple', 'pear', 'orange']
    +
    +
    + +

    or even to work on the DOM:

    + +
    'failure-message, success-message & spinner'.scan(/(\w|-)+/, Element.toggle)
    +// -> 'failure-message, success-message & spinner' (and toggles the visibility of each DOM element)
    +
    +
    + +
    Note
    + +

    Do not use the "g" flag on the regex as this will create an infinite loop.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/startswith/index.html b/doc/1.7_rc1/language/string/prototype/startswith/index.html new file mode 100644 index 000000000..9a697fa1b --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/startswith/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#startsWith + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#startsWith +

    + + + + +
    +
    +
    +
    +
    +
    String#startsWith(substring) → Boolean
    + + +

    Checks if the string starts with substring.

    + +
    Example
    + +
    'Prototype JavaScript'.startsWith('Pro');
    +//-> true
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/strip/index.html b/doc/1.7_rc1/language/string/prototype/strip/index.html new file mode 100644 index 000000000..bf0064984 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/strip/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#strip + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#strip +

    + + + + +
    +
    +
    +
    +
    +
    String#strip() → String
    + + +

    Strips all leading and trailing whitespace from a string.

    + +
    Example
    + +
    '    hello world!    '.strip();
    +// -> 'hello world!'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/stripscripts/index.html b/doc/1.7_rc1/language/string/prototype/stripscripts/index.html new file mode 100644 index 000000000..52d144a42 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/stripscripts/index.html @@ -0,0 +1,184 @@ + + + + + Prototype v1.7_rc1 API documentation | String#stripScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#stripScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#stripScripts() → String
    + + +

    Strips a string of things that look like an HTML script blocks.

    + +
    Example
    + +
    "<p>This is a test.<script>alert("Look, a test!");</script>End of test</p>".stripScripts();
    +// => "<p>This is a test.End of test</p>"
    +
    +
    + +
    Caveat User
    + +

    Note that the processing String#stripScripts does is good enough for +most purposes, but you cannot rely on it for security purposes. If you're +processing end-user-supplied content, String#stripScripts is probably +not sufficiently robust to prevent hack attacks.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/striptags/index.html b/doc/1.7_rc1/language/string/prototype/striptags/index.html new file mode 100644 index 000000000..593e131fc --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/striptags/index.html @@ -0,0 +1,198 @@ + + + + + Prototype v1.7_rc1 API documentation | String#stripTags + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#stripTags +

    + + + + +
    +
    +
    +
    +
    +
    String#stripTags() → String
    + + +

    Strips a string of any HTML tags.

    + +

    Note that String#stripTags will only strip HTML 4.01 tags — like +div, span, and abbr. It will not strip namespace-prefixed tags +such as h:table or xsl:template.

    + +

    Watch out for <script> tags in your string, as String#stripTags will +not remove their content. Use String#stripScripts to do so.

    + +
    Caveat User
    + +

    Note that the processing String#stripTags does is good enough for most +purposes, but you cannot rely on it for security purposes. If you're +processing end-user-supplied content, String#stripTags is not +sufficiently robust to ensure that the content is completely devoid of +HTML tags in the case of a user intentionally trying to circumvent tag +restrictions. But then, you'll be running them through +String#escapeHTML anyway, won't you?

    + +
    Examples
    + +
    'a <a href="#">link</a>'.stripTags();
    + // -> 'a link'
    + 'a <a href="#">link</a><script>alert("hello world!");</script>'.stripTags();
    +// -> 'a linkalert("hello world!");'
    + 'a <a href="#">link</a><script>alert("hello world!");</script>'.stripScripts().stripTags();
    +// -> 'a link'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/sub/index.html b/doc/1.7_rc1/language/string/prototype/sub/index.html new file mode 100644 index 000000000..a826bd9e5 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/sub/index.html @@ -0,0 +1,204 @@ + + + + + Prototype v1.7_rc1 API documentation | String#sub + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#sub +

    + + + + +
    +
    +
    +
    +
    +
    String#sub(pattern, replacement[, count = 1]) → String
    + + +

    Returns a string with the first count occurrences of pattern replaced by either +a regular string, the returned value of a function or a Template string. +pattern can be a string or a regular expression.

    + +

    Unlike String#gsub, String#sub takes a third optional parameter which specifies +the number of occurrences of the pattern which will be replaced. +If not specified, it will default to 1.

    + +

    Apart from that, String#sub works just like String#gsub. +Please refer to it for a complete explanation.

    + +
    Examples
    + +
    var fruits = 'apple pear orange';
    + fruits.sub(' ', ', ');
    +// -> 'apple, pear orange'
    + fruits.sub(' ', ', ', 1);
    +// -> 'apple, pear orange'
    + fruits.sub(' ', ', ', 2);
    +// -> 'apple, pear, orange'
    + fruits.sub(/\w+/, function(match){ return match[0].capitalize() + ',' }, 2);
    +// -> 'Apple, Pear, orange'
    + var markdown = '![a pear](/img/pear.jpg) ![an orange](/img/orange.jpg)';
    + markdown.sub(/!\[(.*?)\]\((.*?)\)/, function(match) {
    +  return '<img alt="' + match[1] + '" src="' + match[2] + '" />';
    +});
    +// -> '<img alt="a pear" src="/img/pear.jpg" /> ![an orange](/img/orange.jpg)'
    + markdown.sub(/!\[(.*?)\]\((.*?)\)/, '<img alt="#{1}" src="#{2}" />');
    +// -> '<img alt="a pear" src="/img/pear.jpg" /> ![an orange](/img/orange.jpg)'
    +
    +
    + +
    Note
    + +

    Do not use the "g" flag on the regex as this will create an infinite loop.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/succ/index.html b/doc/1.7_rc1/language/string/prototype/succ/index.html new file mode 100644 index 000000000..aa36de5ec --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/succ/index.html @@ -0,0 +1,182 @@ + + + + + Prototype v1.7_rc1 API documentation | String#succ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#succ +

    + + + + +
    +
    +
    +
    +
    +
    String#succ() → String
    + + +

    Used internally by ObjectRange.

    + +

    Converts the last character of the string to the following character in +the Unicode alphabet.

    + +
    Examples
    + +
    'a'.succ();
    +// -> 'b'
    + 'aaaa'.succ();
    +// -> 'aaab'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/times/index.html b/doc/1.7_rc1/language/string/prototype/times/index.html new file mode 100644 index 000000000..d3f461645 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/times/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#times + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#times +

    + + + + +
    +
    +
    +
    +
    +
    String#times(count) → String
    + + +

    Concatenates the string count times.

    + +
    Example
    + +
    "echo ".times(3);
    +// -> "echo echo echo "
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/toarray/index.html b/doc/1.7_rc1/language/string/prototype/toarray/index.html new file mode 100644 index 000000000..bbb47c0fc --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/toarray/index.html @@ -0,0 +1,180 @@ + + + + + Prototype v1.7_rc1 API documentation | String#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#toArray +

    + + + + +
    +
    +
    +
    +
    +
    String#toArray() → Array
    + + +

    Splits the string character-by-character and returns an array with +the result.

    + +
    Examples
    + +
    'a'.toArray();
    +// -> ['a']
    + 'hello world!'.toArray();
    +// -> ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/toqueryparams/index.html b/doc/1.7_rc1/language/string/prototype/toqueryparams/index.html new file mode 100644 index 000000000..e3d499096 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/toqueryparams/index.html @@ -0,0 +1,202 @@ + + + + + Prototype v1.7_rc1 API documentation | String#toQueryParams + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#toQueryParams +

    + + + + +
    +
    +
    +
    +
    +
    String#toQueryParams([separator = '&']) → Object
    + + +

    Parses a URI-like query string and returns an object composed of +parameter/value pairs.

    + +

    This method is realy targeted at parsing query strings (hence the default +value of"&" for the separator argument).

    + +

    For this reason, it does not consider anything that is either before a +question mark (which signals the beginning of a query string) or beyond +the hash symbol ("#"), and runs decodeURIComponent() on each +parameter/value pair.

    + +

    String#toQueryParams also aggregates the values of identical keys into +an array of values.

    + +

    Note that parameters which do not have a specified value will be set to +undefined.

    + +
    Examples
    + +
    'section=blog&id=45'.toQueryParams();
    +// -> {section: 'blog', id: '45'}
    + 'section=blog;id=45'.toQueryParams();
    +// -> {section: 'blog', id: '45'}
    + 'http://www.example.com?section=blog&id=45#comments'.toQueryParams();
    +// -> {section: 'blog', id: '45'}
    + 'section=blog&tag=javascript&tag=prototype&tag=doc'.toQueryParams();
    +// -> {section: 'blog', tag: ['javascript', 'prototype', 'doc']}
    + 'tag=ruby%20on%20rails'.toQueryParams();
    +// -> {tag: 'ruby on rails'}
    + 'id=45&raw'.toQueryParams();
    +// -> {id: '45', raw: undefined}
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/truncate/index.html b/doc/1.7_rc1/language/string/prototype/truncate/index.html new file mode 100644 index 000000000..94b8d4e87 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/truncate/index.html @@ -0,0 +1,184 @@ + + + + + Prototype v1.7_rc1 API documentation | String#truncate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#truncate +

    + + + + +
    +
    +
    +
    +
    +
    String#truncate([length = 30[, suffix = '...']]) → String
    + + +

    Truncates a string to given length and appends suffix to it (indicating +that it is only an excerpt).

    + +
    Examples
    + +
    'A random sentence whose length exceeds 30 characters.'.truncate();
    +// -> 'A random sentence whose len...'
    + 'Some random text'.truncate();
    +// -> 'Some random text.'
    + 'Some random text'.truncate(10);
    +// -> 'Some ra...'
    + 'Some random text'.truncate(10, ' [...]');
    +// -> 'Some [...]'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/underscore/index.html b/doc/1.7_rc1/language/string/prototype/underscore/index.html new file mode 100644 index 000000000..0d53f00d9 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/underscore/index.html @@ -0,0 +1,188 @@ + + + + + Prototype v1.7_rc1 API documentation | String#underscore + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#underscore +

    + + + + +
    +
    +
    +
    +
    +
    String#underscore() → String
    + + +

    Converts a camelized string into a series of words separated by an +underscore (_).

    + +
    Example
    + +
    'borderBottomWidth'.underscore();
    +// -> 'border_bottom_width'
    +
    +
    + +
    Note
    + +

    Used in conjunction with String#dasherize, String#underscore +converts a DOM style into its CSS equivalent.

    + +
    'borderBottomWidth'.underscore().dasherize();
    +// -> 'border-bottom-width'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/unescapehtml/index.html b/doc/1.7_rc1/language/string/prototype/unescapehtml/index.html new file mode 100644 index 000000000..d82b2cda1 --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/unescapehtml/index.html @@ -0,0 +1,180 @@ + + + + + Prototype v1.7_rc1 API documentation | String#unescapeHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#unescapeHTML +

    + + + + +
    +
    +
    +
    +
    +
    String#unescapeHTML() → String
    + + +

    Strips tags and converts the entity forms of special HTML characters +to their normal form.

    + +
    Examples
    + +
    'x &gt; 10'.unescapeHTML()
    +// -> 'x > 10'
    + '<h1>Pride &amp; Prejudice</h1>;'.unescapeHTML()
    +// -> '<h1>Pride & Prejudice</h1>'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/string/prototype/unfilterjson/index.html b/doc/1.7_rc1/language/string/prototype/unfilterjson/index.html new file mode 100644 index 000000000..52fb959de --- /dev/null +++ b/doc/1.7_rc1/language/string/prototype/unfilterjson/index.html @@ -0,0 +1,178 @@ + + + + + Prototype v1.7_rc1 API documentation | String#unfilterJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#unfilterJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#unfilterJSON([filter = Prototype.JSONFilter]) → String
    + + +

    Strips comment delimiters around Ajax JSON or JavaScript responses. +This security method is called internally.

    + +
    Example
    + +
    '/*-secure-\n{"name": "Violet", "occupation": "character", "age": 25}\n*\/'.unfilterJSON()
    +// -> '{"name": "Violet", "occupation": "character", "age": 25}'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/template/index.html b/doc/1.7_rc1/language/template/index.html new file mode 100644 index 000000000..1b4dd48d3 --- /dev/null +++ b/doc/1.7_rc1/language/template/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.7_rc1 API documentation | Template + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Template +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A class for sophisticated string interpolation.

    + +

    Any time you have a group of similar objects and you need to produce +formatted output for these objects, maybe inside a loop, you typically +resort to concatenating string literals with the object's fields:

    + +
    "The TV show " + title + " was created by " + author + ".";
    +
    +
    + +

    There's nothing wrong with this approach, except that it is hard to +visualize the output immediately just by glancing at the concatenation +expression. The Template class provides a much nicer and clearer way of +achieving this formatting.

    + +
    Straightforward templates
    + +

    The Template class uses a basic formatting syntax, similar to what is +used in Ruby. The templates are created from strings that have embedded +symbols in the form (e.g., #{fieldName}) that will be replaced by +actual values when the template is applied (evaluated) to an object.

    + +
    // the template (our formatting expression)
    +var myTemplate = new Template(
    + 'The TV show #{title} was created by #{author}.');
    + // our data to be formatted by the template
    +var show = {
    +  title: 'The Simpsons',
    +  author: 'Matt Groening',
    +  network: 'FOX'
    +};
    + // let's format our data
    +myTemplate.evaluate(show);
    +// -> "The TV show The Simpsons was created by Matt Groening."
    +
    +
    + +
    Templates are meant to be reused
    + +

    As the example illustrates, Template objects are not tied to specific +data. The data is bound to the template only during the evaluation of the +template, without affecting the template itself. The next example shows the +same template being used with a handful of distinct objects.

    + +
    // creating a few similar objects
    +var conversion1 = { from: 'meters', to: 'feet', factor: 3.28 };
    +var conversion2 = { from: 'kilojoules', to: 'BTUs', factor: 0.9478 };
    +var conversion3 = { from: 'megabytes', to: 'gigabytes', factor: 1024 };
    + // the template
    +var templ = new Template(
    + 'Multiply by #{factor} to convert from #{from} to #{to}.');
    + // let's format each object
    +[conversion1, conversion2, conversion3].each( function(conv){
    +    templ.evaluate(conv);
    +});
    +// -> Multiply by 3.28 to convert from meters to feet.
    +// -> Multiply by 0.9478 to convert from kilojoules to BTUs.
    +// -> Multiply by 1024 to convert from megabytes to gigabytes.
    +
    +
    + +
    Escape sequence
    + +

    There's always the chance that one day you'll need to have a literal in your +template that looks like a symbol, but is not supposed to be replaced. For +these situations there's an escape character: the backslash (\).

    + +
    // NOTE: you're seeing two backslashes here because the backslash
    +// is also an escape character in JavaScript strings, so a literal
    +// backslash is represented by two backslashes.
    +var t = new Template(
    + 'in #{lang} we also use the \\#{variable} syntax for templates.');
    +var data = { lang:'Ruby', variable: '(not used)' };
    +t.evaluate(data);
    +// -> in Ruby we also use the #{variable} syntax for templates.
    +
    +
    + +
    Custom syntaxes
    + +

    The default syntax of the template strings will probably be enough for most +scenarios. In the rare occasion where the default Ruby-like syntax is +inadequate, there's a provision for customization. Template's +constructor accepts an optional second argument that is a regular expression +object to match the replaceable symbols in the template string. Let's put +together a template that uses a syntax similar to the now ubiquitous {{ }} +constructs:

    + +
    // matches symbols like '{{ field }}'
    +var syntax = /(^|.|\r|\n)(\{{\s*(\w+)\s*}})/;
    + var t = new Template(
    + '<div>Name: <b>{{ name }}</b>, Age: <b>{{ age }}</b></div>',
    + syntax);
    +t.evaluate( {name: 'John Smith', age: 26} );
    +// -> <div>Name: <b>John Smith</b>, Age: <b>26</b></div>
    +
    +
    + +

    There are important constraints to any custom syntax. Any syntax must +provide at least three groupings in the regular expression. The first +grouping is to capture what comes before the symbol, to detect the backslash +escape character (no, you cannot use a different character). The second +grouping captures the entire symbol and will be completely replaced upon +evaluation. Lastly, the third required grouping captures the name of the +field inside the symbol.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Template

    +
    +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/template/new/index.html b/doc/1.7_rc1/language/template/new/index.html new file mode 100644 index 000000000..4d3d4fc28 --- /dev/null +++ b/doc/1.7_rc1/language/template/new/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | new Template + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Template +

    + + + + +
    +
    +
    +
    +
    +
    new(template[, pattern = Template.Pattern])
    + + +

    Creates a Template object.

    + +

    The optional pattern argument expects a RegExp that defines a custom +syntax for the replaceable symbols in template.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/template/prototype/evaluate/index.html b/doc/1.7_rc1/language/template/prototype/evaluate/index.html new file mode 100644 index 000000000..960efc545 --- /dev/null +++ b/doc/1.7_rc1/language/template/prototype/evaluate/index.html @@ -0,0 +1,157 @@ + + + + + Prototype v1.7_rc1 API documentation | Template#evaluate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Template#evaluate +

    + + + + +
    +
    +
    +
    +
    +
    Template#evaluate(object) → String
    + + +

    Applies the template to object's data, producing a formatted string +with symbols replaced by object's corresponding properties.

    + +
    Examples
    + +
    var hrefTemplate = new Template('/dir/showAll?lang=#{language}&amp;categ=#{category}&amp;lv=#{levels}');
    +var selection = {category: 'books' , language: 'en-US'};
    + hrefTemplate.evaluate(selection);
    +// -> '/dir/showAll?lang=en-US&amp;categ=books&amp;lv='
    + hrefTemplate.evaluate({language: 'jp', levels: 3, created: '10/12/2005'});
    +// -> '/dir/showAll?lang=jp&amp;categ=&amp;lv=3'
    + hrefTemplate.evaluate({});
    +// -> '/dir/showAll?lang=&amp;categ=&amp;lv='
    + hrefTemplate.evaluate(null);
    +// -> error !
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/try/index.html b/doc/1.7_rc1/language/try/index.html new file mode 100644 index 000000000..7ed0b256f --- /dev/null +++ b/doc/1.7_rc1/language/try/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Try + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Try +

    + + + + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/1.7_rc1/language/try/these/index.html b/doc/1.7_rc1/language/try/these/index.html new file mode 100644 index 000000000..c173b73c9 --- /dev/null +++ b/doc/1.7_rc1/language/try/these/index.html @@ -0,0 +1,183 @@ + + + + + Prototype v1.7_rc1 API documentation | Try.these + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Try.these +

    + + + + +
    +
    +
    +
    +
    +
    Try.these(function...) → ?
    +
      +
    • + function + (Function) + – A function that may throw an exception. +
    • +
    + + +

    Accepts an arbitrary number of functions and returns the result of the +first one that doesn't throw an error.

    + +

    This method is deprecated.

    + +
    More information
    + +

    Try.these provides a simple idiom for trying out blocks of code in +sequence. Such a sequence of attempts usually represents a downgrading +approach to obtaining a given feature.

    + +

    In this example from Prototype's Ajax internals, we want to get an +XMLHttpRequest object. Internet Explorer 6 and earlier, however, does not +provide it as a vanilla JavaScript object, and will throw an error if we +attempt a simple instantiation. Also, over time, its proprietary way +evolved, changing COM interface names.

    + +

    Try.these will try several ways in sequence, from the best (and, +theoretically, most widespread) one to the oldest and rarest way, returning +the result of the first successful function.

    + +

    If none of the blocks succeeded, Try.these will return undefined, which +will cause the Ajax.getTransport method in the example below to return +false, provided as a fallback result value.

    + +
    var Ajax = {
    +  getTransport: function() {
    +    return Try.these(
    +      function() { return new XMLHttpRequest() },
    +      function() { return new ActiveXObject('Msxml2.XMLHTTP') },
    +      function() { return new ActiveXObject('Microsoft.XMLHTTP') }
    +    ) || false;
    +  }
    +};
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/1.7_rc1/stylesheets/api.css b/doc/1.7_rc1/stylesheets/api.css new file mode 100644 index 000000000..7e28842f8 --- /dev/null +++ b/doc/1.7_rc1/stylesheets/api.css @@ -0,0 +1,687 @@ +/* The "section" class implicitly needs a clearfix; adding it here for convenience. */ + +.clearfix:after, +.section:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; +} + +.clearfix, .section { + display: inline-block; +} + +html[xmlns] .clearfix, +html[xmlns] .section { + display: block; +} + +* html .clearfix, +* html .section { + height: 1%; +} + +span.replaced { visibility: hidden; } +span.hidden { display: none; } + + +body { + font-family: Verdana, sans-serif; + font-size: 82.5%; + line-height: 1.5em; + margin: 0; + padding: 0; +} + + body * { + margin: 0; + padding: 0; + } + +h1, h2, h3, h4, h5, h6 { + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; +} + +pre { + white-space: pre-wrap; /* CSS 3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +a img { + border: 0; +} + +ul, li { + list-style-type: none; +} + +ol, ul { + margin: 0 0 15px; +} + +code, pre { + font-family: "Panic Sans", "Bitstream Vera Sans Mono", Monaco, Consolas, Andale Mono, monospace; + font-size: 12px; +} + +#page a.img, +#page a.img:link, +#page a.img:visited { + border: 0; +} + +.content { + padding-left: 120px; + margin: 0 auto; +} + +#page { + margin: 0; + position: fixed; + top: 0; + bottom: 0; + right: 0; + left: 241px; + overflow-y: scroll; + overflow-x: auto; +} + + +/* MASTHEAD */ + +.masthead { + margin-top: 31px; + height: 75px; + padding: 1px 0; + background: url(../images/header-stripe-small.png) repeat-x; +} + +h1.logo { + width: 236px; + height: 150px; + background: url(../images/header-logo-small.png) no-repeat; +} + + h1.logo a { + text-decoration: none; + } + +/* BREADCRUMBS */ + +ul.breadcrumbs { + margin-left: 120px; + padding-left: 120px; + list-style-type: none; +} + + ul.breadcrumbs li { + float: left; + list-style-type: none; + margin-left: 0; + margin-right: 0.4em; + } + +#deprecated { + position: absolute; + right: 0; + top: 0; +} + +#deprecated img { + display: block; + border: 0; +} + + +/* PAGE CONTENT */ + +.page-content { + width: 715px; + margin: 0 0 30px 0; +} + + .page-content h2.page-title { + margin: 0 0 15px 120px; + line-height: 100%; + font-size: 27px; + letter-spacing: -1px; + color: #444; + } + + .page-introduction { + margin-left: 120px; + margin-bottom: 25px; + } + + .page-content a, + .page-content a:link { + color: #036; + border-bottom: 1px solid #036; + text-decoration: none; + } + + .page-content a:visited { + border-bottom: 1px solid #bbb; + } + + .page-content ul, + .page-content ol { + margin: 10px 0; + } + + .page-content li { + margin: 5px 0 8px 20px; + list-style-type: disc; + } + + .page-content p { + margin: 0 0 0.8em; + } + + .page-content code { + background-color: #f0f0f0; + border: 1px solid #ccc; + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + padding: 0 3px; + } + + .page-content pre { + color: #333; + background-color: #f0f0ff; + border: 1px solid #dde; + padding: 3px 5px; + margin: 0 0 1em; + } + + .page-content pre code { + background-color: transparent; + border: 0; + padding: 0; + line-height: 100%; + } + + + .page-content code { + + } + + .page-content h1 { + font-size: 27px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h2 { + font-size: 23px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h3 { + font-size: 20px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h4 { + font-size: 17px; + color: #555; + margin: 1.0em 0 0.6em; + } + + .page-content h5 { + font-size: 15px; + color: #2a2a2a; + margin: 1.0em 0 0.6em; + } + + .page-content h6 { + font-size: 14px; + color: #000; + margin: 1.0em 0 0.6em; + } + +/* PAGE SECTIONS */ + +.section { + margin: 10px 0 15px; +} + + .section-title { + width: 110px; + float: left; + margin-right: 10px; + padding-right: 0; + padding-bottom: 10px; + text-align: right; + overflow: hidden; + } + + .section-title h3 { + color: #999; + font-size: 14px; + line-height: 110%; + margin-top: 3px; + padding-right: 10px; + padding-bottom: 5px; + } + + .section-content { + width: 595px; + float: left; + } + + +/* API STYLES */ + +.page-title .type { + display: block; + text-transform: uppercase; + font-size: 14px; + color: #aaa; +} + + +ul.section-list { + list-style-type: none; + margin-top: 0; +} + + ul.section-list li { + list-style-type: none; + margin: 0 0 15px; + } + + ul.section-list li h4 { + margin-top: 0; + } + +ul.method-list { + margin-top: 0; +} + + ul.method-list li { + float: left; + margin: 0 5px 3px 0; + list-style-type: none; + padding-bottom: 0; + } + + ul.method-list li a, + ul.method-list li a:link { + text-decoration: none; + border: 0; + } + +ul.method-details-list { + margin-top: 0; +} + + li.method-description { + margin: 0 0 2.0em; + list-style-type: none; + } + + .method-description h4 { + margin: 0 0 0.6em; + line-height: 90%; + } + + .method-description p { + margin: 0.8em 0; + } + + + .method-description .method-permalink a { + color: #aaa; + text-decoration: none; + border-bottom: 0; + font-size: 14px; +} + +h4.inherited { + clear: left; + font-size: 15px; + font-style: italic; +} + +pre.syntax { + margin-bottom: 5px; +} + +ul.argument-list { + font-size: 12px; + padding: 0; + margin: 0; +} + + ul.argument-list li { + line-height: 140%; + margin-top: 0px; + margin-bottom: 5px; + } + + ul.argument-list li code { + font-size: 11px; + } + + ul.argument-list .argument-name { + background-color: #eeffee; + border-color: #6b6; + } + + +/* SECTION ICONS */ + +.page-content .section .section-title h3 { + padding-right: 24px; + background-position: right 0; + background-repeat: no-repeat; +} + +.section-constructor .section-title h3 { + background-image: url(../images/constructor.png); +} + +.section-method-list .section-title h3 { + background-image: url(../images/method.png); +} + +.section-class_methods .section-title h3 { + background-image: url(../images/class_method.png); +} + +.section-class_properties .section-title h3 { + background-image: url(../images/class_property.png); +} + +.section-instance_methods .section-title h3 { + background-image: url(../images/instance_method.png); +} + +.section-instance_properties .section-title h3 { + background-image: url(../images/instance_property.png); +} + +.section-mixins .section-title h3 { + background-image: url(../images/mixin.png); +} + +.section-classes .section-title h3 { + background-image: url(../images/class.png); +} + +.section-namespaces .section-title h3 { + background-image: url(../images/namespace.png); +} + +.section-sections .section-title h3 { + background-image: url(../images/section.png); +} + +.section-utilities .section-title h3 { + background-image: url(../images/utility.png); +} + +.section-description .section-title h3 { + background-image: url(../images/description.png); +} + +.section-subclasses .section-title h3 { + background-image: url(../images/subclass.png); +} + +.section-superclass .section-title h3 { + background-image: url(../images/superclass.png); +} + +/* notes */ + +p.note, +p.alias, +p.related-to { + font-size: 11px; + line-height: 14px; + padding: 5px 20px 5px 60px; + background-repeat: no-repeat; + background-position: 20px 50%; + border: 1px solid #000; +} + +p.note { + background-color: #f0f0f4; + background-image: url(../images/information.png); + border-color: #69c; +} + +p.alias { + background-color: #fff6de; + background-image: url(../images/alias.png); + border-color: #cc9; +} + +p.related-to { + background-color: #f4f0f4; + background-image: url(../images/related_to.png); + border-color: #c9c; +} + +/* SIDEBAR */ + +#sidebar { + position: fixed; + top: 0; + bottom: 0; + left: 0; + width: 240px; + background: #fff; + font-size: 13px; +} + +#sidebar form.search-ribbon { + margin: 0; + height: 24px; + border-right: 1px solid #636363; + padding: 4px 0 3px; + border-bottom: 1px solid #587e93; + background: url(../images/search-background.png) repeat-x 0 0; + text-align: center; +} + +/* Keep these around for `Control.Tabs`. */ +.sidebar-tabs { display: none; } + +.menu-items ul { + margin: 0; +} + + .menu-items ul li { + list-style-type: none; + padding-left: 0; + margin-left: 0; + } + + .menu-items ul .menu-item a { + padding-left: 38px; + background-position: 16px 50%; + } + + .menu-items ul ul .menu-item a { + padding-left: 48px; + background-position: 26px 50%; + } + + .menu-items ul ul ul .menu-item a { + padding-left: 58px; + background-position: 36px 50%; + } + + .menu-items ul ul ul ul .menu-item a { + padding-left: 68px; + background-position: 46px 50%; + } + + + + .menu-item a, + .menu-item a:link { + display: block; + padding: 3px 10px 3px 28px; + background-position: 6px 50%; + background-repeat: no-repeat; + text-align: left; + text-decoration: none; + color: #333; + border-top: 1px solid #fff; + border-bottom: 1px solid #fff; + white-space: nowrap; + } + + .menu-item a:hover, + .menu-item a.highlighted, + #sidebar .highlighted a { + border-top: 1px solid #69f; + border-bottom: 1px solid #69f; + background-color: #f0f0ff; + } + + .menu-item a.current, + #sidebar .current a { + border-top: 1px solid #f0f0ff; + border-bottom: 1px solid #f0f0ff; + background-color: #f0f0ff; + } + + .menu-item a.current-parent, + #sidebar .current-parent a { + border-top: 1px solid #f0f0ff; + border-bottom: 1px solid #f0f0ff; + background-color: #f0f0ff; + } + + .menu-item a.class-method { + background-image: url(../images/class_method.png); + } + + .menu-item a.instance-method { + background-image: url(../images/instance_method.png); + } + + .menu-item a.class { + background-image: url(../images/class.png); + } + + .menu-item a.constructor { + background-image: url(../images/constructor.png); + } + + .menu-item a.class-property { + background-image: url(../images/class_property.png); + } + + .menu-item a.instance-property { + background-image: url(../images/instance_property.png); + } + + .menu-item a.namespace { + background-image: url(../images/namespace.png); + } + + .menu-item a.mixin { + background-image: url(../images/mixin.png); + } + + .menu-item a.utility { + background-image: url(../images/utility.png); + } + + .menu-item a.section { + margin: 0; + background-image: url(../images/section.png); + } + + #api_menu .menu-item a.section { + height: 22px; + font-weight: normal; + color: #a5a5a5; + margin-top: 0; + margin-bottom: 0; + border-top: 1px solid #000; + border-bottom: 1px solid #000; + background: url(../images/section-background.png) repeat-x 0 0; + } + +.menu-section { + margin-bottom: 1.0em; +} + +#menu_pane { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + width: 239px; + border-right: 1px solid #636363; + overflow-y: scroll; + overflow-x: hidden; +} + +#search_pane { + width: 239px; + border-right: 1px solid #636363; + position: absolute; + top: 32px; + bottom: 0; + left: 0; +} + + #search_results { + margin: 0; + padding: 0; + overflow-y: scroll; + overflow-x: hidden; + position: absolute; + top: 0; + bottom: 0; + width: 239px; + } + +#search { + width: 200px; + padding: 2px 3px; +} + +input.ghosted { + font-style: italic; + color: #aaa; +} + + +/* FOOTER */ + +#footer { + color: #bbb; + width: 595px; + margin-left: 120px; + margin-top: 30px; + border-top: 1px solid #ccc; + font-size: 10px; + padding: 1em 0; +} + + #footer a, + #footer a:link { + color: #999; + } + +#src_code_href { + float: right; +} \ No newline at end of file diff --git a/doc/1.7_rc1/stylesheets/pygments.css b/doc/1.7_rc1/stylesheets/pygments.css new file mode 100644 index 000000000..56dee2899 --- /dev/null +++ b/doc/1.7_rc1/stylesheets/pygments.css @@ -0,0 +1,62 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #408080; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ +.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #808080 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #7D9029 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/doc/ajax/ajax/activerequestcount/index.html b/doc/ajax/ajax/activerequestcount/index.html new file mode 100644 index 000000000..d11fb577d --- /dev/null +++ b/doc/ajax/ajax/activerequestcount/index.html @@ -0,0 +1,141 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.activeRequestCount + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Ajax.activeRequestCount +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.activeRequestCount → Number
    + + +

    Represents the number of active XHR requests triggered through +Ajax.Request, Ajax.Updater, or Ajax.PeriodicalUpdater.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/index.html b/doc/ajax/ajax/index.html new file mode 100644 index 000000000..3dd3d27cf --- /dev/null +++ b/doc/ajax/ajax/index.html @@ -0,0 +1,195 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Ajax +

    + + + + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Ajax.Responders

      + +

      A repository of global listeners notified about every step of +Prototype-based Ajax requests.

      +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Ajax.PeriodicalUpdater

      + +

      Periodically performs an Ajax request and updates a container's contents +based on the response text.

      +
    • +
    • +

      Ajax.Request

      + +

      Initiates and processes an Ajax request.

      +
    • +
    • +

      Ajax.Response

      + +

      A wrapper class around XmlHttpRequest for dealing with HTTP responses +of Ajax requests.

      +
    • +
    • +

      Ajax.Updater

      + +

      A class that performs an Ajax request and updates a container's contents +with the contents of the response.

      +
    • +
    +
    +
    + + + + + + + + +
    +
    +

    Class properties

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/ajax/ajax/periodicalupdater/index.html b/doc/ajax/ajax/periodicalupdater/index.html new file mode 100644 index 000000000..94e8f594f --- /dev/null +++ b/doc/ajax/ajax/periodicalupdater/index.html @@ -0,0 +1,209 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.PeriodicalUpdater + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Ajax.PeriodicalUpdater +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Periodically performs an Ajax request and updates a container's contents +based on the response text.

    + +

    Ajax.PeriodicalUpdater behaves like Ajax.Updater, but performs the +update at a prescribed interval, rather than only once. (Note that it is +not a subclass of Ajax.Updater; it's a wrapper around it.)

    + +

    This class addresses the common need of periodical update, as required by +all sorts of "polling" mechanisms (e.g., an online chatroom or an online +mail client).

    + +

    The basic idea is to run a regular Ajax.Updater at regular intervals, +keeping track of the response text so it can (optionally) react to +receiving the exact same response consecutively.

    + +
    Additional options
    + +

    Ajax.PeriodicalUpdater features all the common options and callbacks +described in the Ajaxplus those added by +Ajax.Updater.

    + +

    It also provides two new options:

    + +
      +
    • frequency (Number; default is 2): How long, in seconds, to wait +between the end of one request and the beginning of the next.
    • +
    • decay (Number; default is 1): The rate at which the frequency +grows when the response received is exactly the same as the previous. +The default of 1 means frequency will never grow; override the +default if a stale response implies it's worthwhile to poll less often. +If decay is set to 2, for instance, frequency will double +(2 seconds, 4 seconds, 8 seconds...) each consecutive time the result +is the same; when the result is different once again, frequency will +revert to its original value.
    • +
    + +
    Disabling and re-enabling a Ajax.PeriodicalUpdater
    + +

    You can hit the brakes on a running Ajax.PeriodicalUpdater by calling +Ajax.PeriodicalUpdater#stop. If you wish to re-enable it later, call +Ajax.PeriodicalUpdater#start.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/ajax/ajax/periodicalupdater/new/index.html b/doc/ajax/ajax/periodicalupdater/new/index.html new file mode 100644 index 000000000..ac400ff19 --- /dev/null +++ b/doc/ajax/ajax/periodicalupdater/new/index.html @@ -0,0 +1,310 @@ + + + + + Prototype v1.7_rc1 API documentation | new Ajax.PeriodicalUpdater + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Ajax.PeriodicalUpdater +

    + + + + +
    +
    +
    +
    +
    +
    new(container, url[, options])
    +
      +
    • + container + (String | Element) + – The DOM element whose contents to update as a result of the Ajax request. Can be a DOM node or a string that identifies a node's ID. +
    • +
    • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
    • +
    • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
    • +
    + + +

    Creates a new Ajax.PeriodicalUpdater.

    + +

    Periodically performs an AJAX request and updates a container's contents +based on the response text. Offers a mechanism for "decay," which lets it +trigger at widening intervals while the response is unchanged.

    + +

    This object addresses the common need of periodical update, which is used +by all sorts of "polling" mechanisms (e.g. in an online chatroom or an +online mail client).

    + +

    The basic idea is to run a regular Ajax.Updater at +regular intervals, monitoring changes in the response text if the decay +option (see below) is active.

    + +
    Additional options
    + +

    Ajax.PeriodicalUpdater features all the common options and callbacks +(see the Ajax for more information), plus those added by +Ajax.Updater. It also provides two new options that deal with the +original period, and its decay rate (how Rocket Scientist does that make +us sound, uh?!).

    + + + + + + + + + + + + + + + + + + + + + +
    OptionDefaultDescription
    frequency2Okay, this is not a frequency (e.g 0.5Hz), but a period (i.e. a number of seconds). +Don't kill me, I didn't write this one! This is the minimum interval at which AJAX +requests are made. You don't want to make it too short (otherwise you may very well +end up with multiple requests in parallel, if they take longer to process and return), +but you technically can provide a number below one, e.g. 0.75 second.
    decay1This controls the rate at which the request interval grows when the response is +unchanged. It is used as a multiplier on the current period (which starts at the original +value of the frequency parameter). Every time a request returns an unchanged +response text, the current period is multiplied by the decay. Therefore, the default +value means regular requests (no change of interval). Values higher than one will +yield growing intervals. Values below one are dangerous: the longer the response text +stays the same, the more often you'll check, until the interval is so short your browser +is left with no other choice than suicide. Note that, as soon as the response text +does change, the current period resets to the original one.
    + +

    To better understand decay, here is a small sequence of calls from the +following example:

    + +
    new Ajax.PeriodicalUpdater('items', '/items', {
    +  method: 'get', frequency: 3, decay: 2
    +});
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Call#When?Decay beforeResponse changed?Decay afterNext periodComments
    100:002n/a13Response is deemed changed, since there is no prior response to compare to!
    200:031yes13Response did change again: we "reset" to 1, which was already the decay.
    300:061no26Response didn't change: decay augments by the decay option factor: +we're waiting longer now…
    400:122no412Still no change, doubling again.
    500:244no824Jesus, is this thing going to change or what?
    600:488yes13Ah, finally! Resetting decay to 1, and therefore using the original period.
    + +
    Disabling and re-enabling a Ajax.PeriodicalUpdater
    + +

    You can pull the brake on a running Ajax.PeriodicalUpdater by simply +calling its stop method. If you wish to re-enable it later, just call +its start method. Both take no argument.

    + +
    Beware! Not a specialization!
    + +

    Ajax.PeriodicalUpdater is not a specialization of Ajax.Updater, +despite its name. When using it, do not expect to be able to use methods +normally provided by Ajax.Request and "inherited" by Ajax.Updater, +such as evalJSON or getHeader. Also the onComplete callback is +hijacked to be used for update management, so if you wish to be notified +of every successful request, use onSuccess instead (beware: it will get +called before the update is performed).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/periodicalupdater/prototype/start/index.html b/doc/ajax/ajax/periodicalupdater/prototype/start/index.html new file mode 100644 index 000000000..b6eec1fae --- /dev/null +++ b/doc/ajax/ajax/periodicalupdater/prototype/start/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.PeriodicalUpdater#start + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.PeriodicalUpdater#start +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.PeriodicalUpdater#start() → undefined
    + + +

    Starts the periodical updater (if it had previously been stopped with +Ajax.PeriodicalUpdater#stop).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/periodicalupdater/prototype/stop/index.html b/doc/ajax/ajax/periodicalupdater/prototype/stop/index.html new file mode 100644 index 000000000..0c2bb68cc --- /dev/null +++ b/doc/ajax/ajax/periodicalupdater/prototype/stop/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.PeriodicalUpdater#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.PeriodicalUpdater#stop +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.PeriodicalUpdater#stop() → undefined
    + + +

    Stops the periodical updater.

    + +

    Also calls the onComplete callback, if one has been defined.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/request/index.html b/doc/ajax/ajax/request/index.html new file mode 100644 index 000000000..654f10733 --- /dev/null +++ b/doc/ajax/ajax/request/index.html @@ -0,0 +1,338 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Ajax.Request +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Initiates and processes an Ajax request.

    + +

    Ajax.Request is a general-purpose class for making HTTP requests which +handles the life-cycle of the request, handles the boilerplate, and lets +you plug in callback functions for your custom needs.

    + +

    In the optional options hash, you usually provide an onComplete and/or +onSuccess callback, unless you're in the edge case where you're getting a +JavaScript-typed response, that will automatically be eval'd.

    + +

    For a full list of common options and callbacks, see "Ajax options" heading +of the Ajax.

    + +
    A basic example
    + +
    new Ajax.Request('/your/url', {
    +  onSuccess: function(response) {
    +    // Handle the response content...
    +  }
    +});
    +
    +
    + +
    Request life-cycle
    + +

    Underneath our nice requester objects lies, of course, XMLHttpRequest. The +defined life-cycle is as follows:

    + +
      +
    1. Created
    2. +
    3. Initialized
    4. +
    5. Request sent
    6. +
    7. Response being received (can occur many times, as packets come in)
    8. +
    9. Response received, request complete
    10. +
    + +

    As you can see under the "Ajax options" heading of the Ajax, +Prototype's AJAX objects define a whole slew of callbacks, which are +triggered in the following order:

    + +
      +
    1. onCreate (this is actually a callback reserved to Ajax.Responders)
    2. +
    3. onUninitialized (maps on Created)
    4. +
    5. onLoading (maps on Initialized)
    6. +
    7. onLoaded (maps on Request sent)
    8. +
    9. onInteractive (maps on Response being received)
    10. +
    11. onXYZ (numerical response status code), onSuccess or onFailure (see below)
    12. +
    13. onComplete
    14. +
    + +

    The two last steps both map on Response received, in that order. If a +status-specific callback is defined, it gets invoked. Otherwise, if +onSuccess is defined and the response is deemed a success (see below), it +is invoked. Otherwise, if onFailure is defined and the response is not +deemed a sucess, it is invoked. Only after that potential first callback is +onComplete called.

    + +
    A note on portability
    + +

    Depending on how your browser implements XMLHttpRequest, one or more +callbacks may never be invoked. In particular, onLoaded and +onInteractive are not a 100% safe bet so far. However, the global +onCreate, onUninitialized and the two final steps are very much +guaranteed.

    + +
    onSuccess and onFailure, the under-used callbacks
    + +

    Way too many people use Ajax.Request in a similar manner to raw XHR, +defining only an onComplete callback even when they're only interested in +"successful" responses, thereby testing it by hand:

    + +
    // This is too bad, there's better!
    +new Ajax.Request('/your/url', {
    +  onComplete: function(response) {
    +    if (200 == response.status)
    +      // yada yada yada
    +  }
    +});
    +
    +
    + +

    First, as described below, you could use better "success" detection: success +is generally defined, HTTP-wise, as either no response status or a "2xy" +response status (e.g., 201 is a success, too). See the example below.

    + +

    Second, you could dispense with status testing altogether! Prototype adds +callbacks specific to success and failure, which we listed above. Here's +what you could do if you're only interested in success, for instance:

    + +
    new Ajax.Request('/your/url', {
    +  onSuccess: function(response) {
    +      // yada yada yada
    +  }
    +});
    +
    +
    + +
    Automatic JavaScript response evaluation
    + +

    If an Ajax request follows the same-origin policy and its response +has a JavaScript-related Content-type, the content of the responseText +property will automatically be passed to eval.

    + +

    In other words: you don't even need to provide a callback to leverage +pure-JavaScript Ajax responses. This is the convention that drives Rails's +RJS.

    + +

    The list of JavaScript-related MIME-types handled by Prototype is:

    + +
      +
    • application/ecmascript
    • +
    • application/javascript
    • +
    • application/x-ecmascript
    • +
    • application/x-javascript
    • +
    • text/ecmascript
    • +
    • text/javascript
    • +
    • text/x-ecmascript
    • +
    • text/x-javascript
    • +
    + +

    The MIME-type string is examined in a case-insensitive manner.

    + +
    Methods you may find useful
    + +

    Instances of the Ajax.Request object provide several methods that come +in handy in your callback functions, especially once the request is complete.

    + +
    Is the response a successful one?
    + +

    The Ajax.Request#success method examines the XHR object's status +property and follows general HTTP guidelines: unknown status is deemed +successful, as is the whole 2xy status code family. It's a generally +better way of testing your response than the usual +200 == transport.status.

    + +
    Getting HTTP response headers
    + +

    While you can obtain response headers from the XHR object using its +getResponseHeader method, this makes for verbose code, and several +implementations raise an exception when the header is not found. To make +this easier, you can use the Ajax.Response#getHeader method, which +delegates to the longer version and returns null if an exception occurs:

    + +
    new Ajax.Request('/your/url', {
    +  onSuccess: function(response) {
    +    // Note how we brace against null values
    +    if ((response.getHeader('Server') || '').match(/Apache/))
    +      ++gApacheCount;
    +    // Remainder of the code
    +  }
    +});
    +
    +
    + +
    Evaluating JSON headers
    + +

    Some backends will return JSON not as response text, but in the X-JSON +header. In this case, you don't even need to evaluate the returned JSON +yourself, as Prototype automatically does so. It passes the result as the +headerJSON property of the Ajax.Response object. Note that if there +is no such header — or its contents are invalid — headerJSON +will be set to null.

    + +
    new Ajax.Request('/your/url', {
    +  onSuccess: function(transport) {
    +    transport.headerJSON
    +  }
    +});
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/ajax/ajax/request/new/index.html b/doc/ajax/ajax/request/new/index.html new file mode 100644 index 000000000..072c012a8 --- /dev/null +++ b/doc/ajax/ajax/request/new/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | new Ajax.Request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Ajax.Request +

    + + + + +
    +
    +
    +
    +
    +
    new(url[, options])
    +
      +
    • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
    • +
    • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
    • +
    + + +

    Creates a new Ajax.Request.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/request/prototype/getheader/index.html b/doc/ajax/ajax/request/prototype/getheader/index.html new file mode 100644 index 000000000..b31ba4e8c --- /dev/null +++ b/doc/ajax/ajax/request/prototype/getheader/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Request#getHeader + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Request#getHeader +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Request#getHeader(name) → String | null
    +
      +
    • + name + (String) + – The name of an HTTP header that may have been part of the response. +
    • +
    + + +

    Returns the value of the given response header, or null if that header +was not found.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/request/prototype/success/index.html b/doc/ajax/ajax/request/prototype/success/index.html new file mode 100644 index 000000000..4e476cc8b --- /dev/null +++ b/doc/ajax/ajax/request/prototype/success/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Request#success + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Request#success +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Request#success() → Boolean
    + + +

    Tests whether the request was successful.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/responders/index.html b/doc/ajax/ajax/responders/index.html new file mode 100644 index 000000000..846f01d51 --- /dev/null +++ b/doc/ajax/ajax/responders/index.html @@ -0,0 +1,223 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Responders + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Ajax.Responders +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A repository of global listeners notified about every step of +Prototype-based Ajax requests.

    + +

    Sometimes, you need to provide generic behaviors over all Ajax operations +happening on the page (through Ajax.Request, Ajax.Updater or +Ajax.PeriodicalUpdater).

    + +

    For instance, you might want to automatically show an indicator when an +Ajax request is ongoing, and hide it when none are. You may well want to +factor out exception handling as well, logging those somewhere on the page +in a custom fashion. The possibilities are myriad.

    + +

    To achieve this, Prototype provides Ajax.Responders, which lets you +register (and, if you wish, unregister later) responders, which are +objects with specially-named methods. These names come from a set of +general callbacks corresponding to different points in time (or outcomes) +of an Ajax request's life cycle.

    + +

    For instance, Prototype automatically registers a responder that maintains +a nifty variable: Ajax.activeRequestCount. This represents, at a given +time, the number of currently active Ajax requests — by monitoring their +onCreate and onComplete events. The code for this is fairly simple:

    + +
    Ajax.Responders.register({
    +  onCreate: function() {
    +    Ajax.activeRequestCount++;
    +  },
    +  onComplete: function() {
    +    Ajax.activeRequestCount--;
    +  }
    +});
    +
    +
    + +
    Responder callbacks
    + +

    The callbacks for responders are similar to the callbacks described in +the Ajax, but take a different signature. They're invoked with +three parameters: the requester object (i.e., the corresponding "instance" +of Ajax.Request), the XMLHttpRequest object, and the result of +evaluating the X-JSON response header, if any (can be null). They also +execute in the context of the responder, bound to the this reference.

    + +
      +
    • onCreate: Triggered whenever a requester object from the Ajax +namespace is created, after its parameters are adjusted and before its +XHR connection is opened. This takes two arguments: the requester +object and the underlying XHR object.
    • +
    • onUninitialized (Not guaranteed): Invoked just after the XHR object +is created.
    • +
    • onLoading (Not guaranteed): Triggered when the underlying XHR object +is being setup, and its connection opened.
    • +
    • onLoaded (Not guaranteed): Triggered once the underlying XHR object +is setup, the connection is open, and it is ready to send its actual +request.
    • +
    • onInteractive (Not guaranteed): Triggered whenever the requester +receives a part of the response (but not the final part), should it +be sent in several packets.
    • +
    • onException: Triggered whenever an XHR error arises. Has a custom +signature: the first argument is the requester (i.e. an Ajax.Request +instance), and the second is the exception object.
    • +
    • onComplete: Triggered at the very end of a request's life-cycle, after +the request completes, status-specific callbacks are called, and possible +automatic behaviors are processed. Guaranteed to run regardless of what +happened during the request.
    • +
    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/ajax/ajax/responders/register/index.html b/doc/ajax/ajax/responders/register/index.html new file mode 100644 index 000000000..4cf9e15fb --- /dev/null +++ b/doc/ajax/ajax/responders/register/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Responders.register + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Ajax.Responders.register +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Responders.register(responder) → undefined
    +
      +
    • + responder + (Object) + – A list of functions with keys corresponding to the names of possible callbacks. +
    • +
    + + +

    Add a group of responders to all Ajax requests.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/responders/unregister/index.html b/doc/ajax/ajax/responders/unregister/index.html new file mode 100644 index 000000000..0ae766cb1 --- /dev/null +++ b/doc/ajax/ajax/responders/unregister/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Responders.unregister + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Ajax.Responders.unregister +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Responders.unregister(responder) → undefined
    +
      +
    • + responder + (Object) + – A list of functions with keys corresponding to the names of possible callbacks. +
    • +
    + + +

    Remove a previously-added group of responders.

    + +

    As always, unregistering something requires you to use the very same +object you used at registration. If you plan to use unregister, be sure +to assign your responder to a variable before passing it into +Ajax.Responders#register — don't pass it an object literal.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/index.html b/doc/ajax/ajax/response/index.html new file mode 100644 index 000000000..b8dde8dca --- /dev/null +++ b/doc/ajax/ajax/response/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Ajax.Response +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A wrapper class around XmlHttpRequest for dealing with HTTP responses +of Ajax requests.

    + +

    An instance of Ajax.Response is passed as the first argument of all Ajax +requests' callbacks. You will not need to create instances of +Ajax.Response yourself.

    +
    +
    + + + + + + + + + + +
    +
    +

    Instance properties

    +
    + +
    + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/getallheaders/index.html b/doc/ajax/ajax/response/prototype/getallheaders/index.html new file mode 100644 index 000000000..ab7c5f2f2 --- /dev/null +++ b/doc/ajax/ajax/response/prototype/getallheaders/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#getAllHeaders + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Response#getAllHeaders +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#getAllHeaders() → String | null
    + + +

    Returns a String containing all headers separated by line breaks. +Does not throw errors if no headers are present the way its native +counterpart does.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/getallresponseheaders/index.html b/doc/ajax/ajax/response/prototype/getallresponseheaders/index.html new file mode 100644 index 000000000..52157471b --- /dev/null +++ b/doc/ajax/ajax/response/prototype/getallresponseheaders/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#getAllResponseHeaders + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Response#getAllResponseHeaders +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#getAllResponseHeaders() → String
    + + +

    Returns a String containing all headers separated by line breaks; throws +an error if no headers exist. This is just a wrapper around the +XmlHttpRequest method of the same name. Prefer it's shorter counterpart: +Ajax.Response#getAllHeaders.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/getheader/index.html b/doc/ajax/ajax/response/prototype/getheader/index.html new file mode 100644 index 000000000..d5dbb43fd --- /dev/null +++ b/doc/ajax/ajax/response/prototype/getheader/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#getHeader + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Response#getHeader +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#getHeader(name) → String | null
    + + +

    See Ajax.Request#getHeader.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/getresponseheader/index.html b/doc/ajax/ajax/response/prototype/getresponseheader/index.html new file mode 100644 index 000000000..8ddcb1868 --- /dev/null +++ b/doc/ajax/ajax/response/prototype/getresponseheader/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#getResponseHeader + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Ajax.Response#getResponseHeader +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#getResponseHeader(name) → String
    + + +

    Returns the value of the requested header if present; throws an error +otherwise. This is just a wrapper around the XmlHttpRequest method of +the same name. Prefer it's shorter counterpart: +Ajax.Response#getHeader.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/headerjson/index.html b/doc/ajax/ajax/response/prototype/headerjson/index.html new file mode 100644 index 000000000..6a9d17289 --- /dev/null +++ b/doc/ajax/ajax/response/prototype/headerjson/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#headerJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#headerJSON +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#headerJSON → Object | Array | null
    + + +

    Auto-evaluated content of the X-JSON header if present; null otherwise. +This is useful to transfer small amounts of data.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/readystate/index.html b/doc/ajax/ajax/response/prototype/readystate/index.html new file mode 100644 index 000000000..f446c4831 --- /dev/null +++ b/doc/ajax/ajax/response/prototype/readystate/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#readyState + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#readyState +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#readyState → Number
    + + +

    A Number corresponding to the request's current state.

    + +

    0 : "Uninitialized"
    +1 : "Loading"
    +2 : "Loaded"
    +3 : "Interactive"
    +4 : "Complete"

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/request/index.html b/doc/ajax/ajax/response/prototype/request/index.html new file mode 100644 index 000000000..81da96788 --- /dev/null +++ b/doc/ajax/ajax/response/prototype/request/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#request +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#request → Ajax.Request | Ajax.Updater
    + + +

    The request object itself (an instance of Ajax.Request or +Ajax.Updater).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/responsejson/index.html b/doc/ajax/ajax/response/prototype/responsejson/index.html new file mode 100644 index 000000000..59a72b5cc --- /dev/null +++ b/doc/ajax/ajax/response/prototype/responsejson/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#responseJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#responseJSON +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#responseJSON → Object | Array | null
    + + +

    The JSON body of the response if the Content-type of the request is set +to application/json; null otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/responsetext/index.html b/doc/ajax/ajax/response/prototype/responsetext/index.html new file mode 100644 index 000000000..eedfac9eb --- /dev/null +++ b/doc/ajax/ajax/response/prototype/responsetext/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#responseText + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#responseText +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#responseText → String
    + + +

    The text body of the response.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/responsexml/index.html b/doc/ajax/ajax/response/prototype/responsexml/index.html new file mode 100644 index 000000000..85ddd700e --- /dev/null +++ b/doc/ajax/ajax/response/prototype/responsexml/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#responseXML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#responseXML +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#responseXML → document | null
    + + +

    The XML body of the response if the Content-type of the request is set +to application/xml; null otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/status/index.html b/doc/ajax/ajax/response/prototype/status/index.html new file mode 100644 index 000000000..263db4ed0 --- /dev/null +++ b/doc/ajax/ajax/response/prototype/status/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#status + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#status +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#status → Number
    + + +

    The HTTP status code sent by the server.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/statustext/index.html b/doc/ajax/ajax/response/prototype/statustext/index.html new file mode 100644 index 000000000..420322dd9 --- /dev/null +++ b/doc/ajax/ajax/response/prototype/statustext/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#statusText + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#statusText +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#statusText → String
    + + +

    The HTTP status text sent by the server.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/response/prototype/transport/index.html b/doc/ajax/ajax/response/prototype/transport/index.html new file mode 100644 index 000000000..33da09861 --- /dev/null +++ b/doc/ajax/ajax/response/prototype/transport/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Response#transport + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Ajax.Response#transport +

    + + + + +
    +
    +
    +
    +
    +
    Ajax.Response#transport → XmlHttpRequest
    + + +

    The native XmlHttpRequest object itself.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/ajax/updater/index.html b/doc/ajax/ajax/updater/index.html new file mode 100644 index 000000000..5f0730bb9 --- /dev/null +++ b/doc/ajax/ajax/updater/index.html @@ -0,0 +1,231 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax.Updater + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Ajax.Updater +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A class that performs an Ajax request and updates a container's contents +with the contents of the response.

    + +

    Ajax.Updater is a subclass of Ajax.Request built for a common +use-case.

    + +
    Example
    + +
    new Ajax.Updater('items', '/items', {
    +  parameters: { text: $F('text') }
    +});
    +
    +
    + +

    This example will make a request to the URL /items (with the given +parameters); it will then replace the contents of the element with the ID +of items with whatever response it receives.

    + +
    Callbacks
    + +

    Ajax.Updater supports all the callbacks listed in the Ajax. +Note that the onComplete callback will be invoked after the element +is updated.

    + +
    Additional options
    + +

    Ajax.Updater has some options of its own apart from the common options +described in the Ajax:

    + +
      +
    • evalScripts (Boolean; defaults to false): Whether <script> +elements in the response text should be evaluated.
    • +
    • insertion (String): By default, Element.update is used, meaning +the contents of the response will replace the entire contents of the +container. You may instead insert the response text without disrupting +existing contents. The insertion option takes one of four strings — +top, bottom, before, or after — and inserts the contents +of the response in the manner described by Element#insert.
    • +
    + +
    More About evalScripts
    + +

    If you use evalScripts: true, any inline <script> block will be +evaluated. This does not mean it will be evaluated in the global scope; +it won't, and that has important ramifications for your var and function +statements. Also note that only inline <script> blocks are supported; +external scripts are ignored. See String#evalScripts for the details.

    + +
    Single container, or success/failure split?
    + +

    The examples above all assume you're going to update the same container +whether your request succeeds or fails. Instead, you may want to update +only for successful requests, or update a different container on failed +requests.

    + +

    To achieve this, you can pass an object instead of a DOM element for the +container parameter. This object must have a success property whose +value identifies the container to be updated on successful requests.

    + +

    If you also provide it with a failure property, its value will be used as +the container for failed requests.

    + +

    In the following code, only successful requests get an update:

    + +
    new Ajax.Updater({ success: 'items' }, '/items', {
    +  parameters: { text: $F('text') },
    +  insertion: 'bottom'
    +});
    +
    +
    + +

    This next example assumes failed requests will deliver an error message as +response text — one that should be shown to the user in another area:

    + +
    new Ajax.Updater({ success: 'items', failure: 'notice' }, '/items',
    +  parameters: { text: $F('text') },
    +  insertion: 'bottom'
    +});
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + + +
    + + + +
    + + diff --git a/doc/ajax/ajax/updater/new/index.html b/doc/ajax/ajax/updater/new/index.html new file mode 100644 index 000000000..4ea2a68fe --- /dev/null +++ b/doc/ajax/ajax/updater/new/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.7_rc1 API documentation | new Ajax.Updater + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Ajax.Updater +

    + + + + +
    +
    +
    +
    +
    +
    new(container, url[, options])
    +
      +
    • + container + (String | Element) + – The DOM element whose contents to update as a result of the Ajax request. Can be a DOM node or a string that identifies a node's ID. +
    • +
    • + url + (String) + – The URL to fetch. When the same-origin policy is in effect (as it is in most cases), url must be a relative URL or an absolute URL that starts with a slash (i.e., it must not begin with http). +
    • +
    • + options + (Object) + – Configuration for the request. See the Ajax for more information. +
    • +
    + + +

    Creates a new Ajax.Updater.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/ajax/index.html b/doc/ajax/index.html new file mode 100644 index 000000000..e0d613204 --- /dev/null +++ b/doc/ajax/index.html @@ -0,0 +1,268 @@ + + + + + Prototype v1.7_rc1 API documentation | Ajax section + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +

    + section Ajax section +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Prototype's APIs around the XmlHttpRequest object.

    + +

    The Prototype framework enables you to deal with Ajax calls in a manner that +is both easy and compatible with all modern browsers.

    + +

    Actual requests are made by creating instances of Ajax.Request.

    + +
    Request headers
    + +

    The following headers are sent with all Ajax requests (and can be +overridden with the requestHeaders option described below):

    + +
      +
    • X-Requested-With is set to XMLHttpRequest.
    • +
    • X-Prototype-Version is set to Prototype's current version (e.g., +<%= PROTOTYPE_VERSION %>).
    • +
    • Accept is set to text/javascript, text/html, application/xml, +text/xml, * / *
    • +
    • Content-type is automatically determined based on the contentType +and encoding options.
    • +
    + +
    Ajax options
    + +

    All Ajax classes share a common set of options and callbacks. +Callbacks are called at various points in the life-cycle of a request, and +always feature the same list of arguments.

    + +
    Common options
    + +
      +
    • asynchronous (Boolean; default true): Determines whether +XMLHttpRequest is used asynchronously or not. Synchronous usage is +strongly discouraged — it halts all script execution for the +duration of the request and blocks the browser UI.
    • +
    • contentType (String; default application/x-www-form-urlencoded): +The Content-type header for your request. Change this header if you +want to send data in another format (like XML).
    • +
    • encoding (String; default UTF-8): The encoding for the contents +of your request. It is best left as-is, but should weird encoding issues +arise, you may have to tweak this.
    • +
    • method (String; default post): The HTTP method to use for the +request. The other common possibility is get. Abiding by Rails +conventions, Prototype also reacts to other HTTP verbs (such as put and +delete) by submitting via post and adding a extra _method parameter +with the originally-requested method.
    • +
    • parameters (String): The parameters for the request, which will be +encoded into the URL for a get method, or into the request body for the +other methods. This can be provided either as a URL-encoded string, a +Hash, or a plain Object.
    • +
    • postBody (String): Specific contents for the request body on a +post method. If it is not provided, the contents of the parameters +option will be used instead.
    • +
    • requestHeaders (Object): A set of key-value pairs, with properties +representing header names.
    • +
    • evalJS (Boolean | String; default true): Automatically evals +the content of Ajax.Response#responseText and populates +Ajax.Response#responseJSON with it if the Content-type returned by +the server is set to application/json. If the request doesn't obey +same-origin policy, the content is sanitized before evaluation. If you +need to force evalutation, pass 'force'. To prevent it altogether, pass +false.
    • +
    • sanitizeJSON (Boolean; default is false for same-origin requests, +true otherwise): Sanitizes the contents of +Ajax.Response#responseText before evaluating it.
    • +
    + +
    Common callbacks
    + +

    When used on individual instances, all callbacks (except onException) are +invoked with two parameters: the Ajax.Response object and the result of +evaluating the X-JSON response header, if any (can be null).

    + +

    For another way of describing their chronological order and which callbacks +are mutually exclusive, see Ajax.Request.

    + +
      +
    • onCreate: Triggered when the Ajax.Request object is initialized. +This is after the parameters and the URL have been processed, but +before opening the connection via the XHR object.
    • +
    • onUninitialized (Not guaranteed): Invoked just after the XHR object +is created.
    • +
    • onLoading (Not guaranteed): Triggered when the underlying XHR object +is being setup, and its connection opened.
    • +
    • onLoaded (Not guaranteed): Triggered once the underlying XHR object +is setup, the connection is open, and it is ready to send its actual +request.
    • +
    • onInteractive (Not guaranteed): Triggered whenever the requester +receives a part of the response (but not the final part), should it +be sent in several packets.
    • +
    • onSuccess: Invoked when a request completes and its status code is +undefined or belongs in the 2xy family. This is skipped if a +code-specific callback is defined (e.g., on200), and happens before +onComplete.
    • +
    • onFailure: Invoked when a request completes and its status code exists +but is not in the 2xy family. This is skipped if a code-specific +callback is defined (e.g. on403), and happens before onComplete.
    • +
    • onXYZ (with XYZ representing any HTTP status code): Invoked just +after the response is complete _if_ the status code is the exact code +used in the callback name. Prevents execution of onSuccess and +onFailure. Happens before onComplete.
    • +
    • onException: Triggered whenever an XHR error arises. Has a custom +signature: the first argument is the requester (i.e. an Ajax.Request +instance), and the second is the exception object.
    • +
    • onComplete: Triggered at the very end of a request's life-cycle, after +the request completes, status-specific callbacks are called, and possible +automatic behaviors are processed. Guaranteed to run regardless of what +happened during the request.
    • +
    +
    +
    + + + +
    +
    +

    Utilities

    +
    +
    + +
      +
    +
    +
    + + +
    +
    +

    Namespaces

    +
    +
    + + +
    +
    + + + +
    + + + +
    + + diff --git a/doc/dom/abstract/eventobserver/index.html b/doc/dom/abstract/eventobserver/index.html new file mode 100644 index 000000000..5ec26e630 --- /dev/null +++ b/doc/dom/abstract/eventobserver/index.html @@ -0,0 +1,132 @@ + + + + + Prototype v1.7_rc1 API documentation | Abstract.EventObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Abstract.EventObserver +

    + + + + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/dom/abstract/index.html b/doc/dom/abstract/index.html new file mode 100644 index 000000000..6a09d1e36 --- /dev/null +++ b/doc/dom/abstract/index.html @@ -0,0 +1,152 @@ + + + + + Prototype v1.7_rc1 API documentation | Abstract + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Abstract +

    + + + + + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Abstract.EventObserver

      + +
    • +
    • +

      Abstract.TimedObserver

      + +

      An abstract DOM element observer class, subclasses of which can be used to +periodically check a value and trigger a callback when the value has changed.

      +
    • +
    +
    +
    + + + + + + + + + +
    + + + +
    + + diff --git a/doc/dom/abstract/timedobserver/index.html b/doc/dom/abstract/timedobserver/index.html new file mode 100644 index 000000000..75c82e1f0 --- /dev/null +++ b/doc/dom/abstract/timedobserver/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Abstract.TimedObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Abstract.TimedObserver +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    An abstract DOM element observer class, subclasses of which can be used to +periodically check a value and trigger a callback when the value has changed.

    + +

    A TimedObserver object will try to check a value using the getValue() +instance method which must be defined by the subclass. There are two +out-of-the-box subclasses: +Form.Observer, which serializes a form and triggers when the result has +changed; and Form.Element.Observer, which triggers when the value of a +given form field changes.

    + +

    Using TimedObserver implementations is straightforward; simply instantiate +them with appropriate arguments. For example:

    + +
    new Form.Element.Observer(
    +  'myelement',
    +  0.2,  // 200 milliseconds
    +  function(el, value){
    +    alert('The form control has changed value to: ' + value)
    +  }
    +)
    +
    +
    + +

    Now that we have instantiated an object, it will check the value of the form +control every 0.2 seconds and alert us of any change. While it is useless to +alert the user of his own input (like in the example), we could be doing +something useful like updating a certain part of the UI or informing the +application on server of stuff happening (over Ajax).

    + +

    The callback function is always called with 2 arguments: the element given +when the observer instance was made and the actual value that has changed +and caused the callback to be triggered in the first place.

    + +
    Creating Your Own TimedObserver Implementations
    + +

    It's easy to create your own TimedObserver implementations: Simply subclass +TimedObserver and provide the getValue() method. For example, this is the +complete source code for Form.Element.Observer:

    + +
    Form.Element.Observer = Class.create(Abstract.TimedObserver, {
    +  getValue: function() {
    +    return Form.Element.getValue(this.element);
    +  }
    +});
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + + +
    + + + +
    + + diff --git a/doc/dom/abstract/timedobserver/new/index.html b/doc/dom/abstract/timedobserver/new/index.html new file mode 100644 index 000000000..b95639367 --- /dev/null +++ b/doc/dom/abstract/timedobserver/new/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.7_rc1 API documentation | new Abstract.TimedObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Abstract.TimedObserver +

    + + + + +
    +
    +
    +
    +
    +
    new(element, frequency, callback)
    +
      +
    • + element + (String | Element) + – The DOM element to watch. Can be an element instance or an ID. +
    • +
    • + frequency + (Number) + – The frequency, in seconds — e.g., 0.33 to check for changes every third of a second. +
    • +
    • + callback + (Function) + – The callback to trigger when the value changes. +
    • +
    + + +

    Initializes an Abstract.TimedObserver; used by subclasses.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/fire/index.html b/doc/dom/document/fire/index.html new file mode 100644 index 000000000..c74e45483 --- /dev/null +++ b/doc/dom/document/fire/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.7_rc1 API documentation | document.fire + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.fire +

    + + + + +
    +
    +
    +
    +
    +
    document.fire(eventName[, memo[, bubble = true]]) → Event
    +
      +
    • + memo + (?) + – Metadata for the event. Will be accessible through the event's memo property. +
    • +
    • + bubble + (Boolean) + – Whether the event will bubble. +
    • +
    + + +

    Fires a custom event of name eventName with document as the target.

    + +

    document.fire is the document-wide version of Element.fire.

    + +

    Custom events must include a colon (:) in their names.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/index.html b/doc/dom/document/index.html new file mode 100644 index 000000000..d22628ba3 --- /dev/null +++ b/doc/dom/document/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | document + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace document +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Prototype extends the built-in document object with several convenience +methods related to events.

    +
    +
    + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      document.viewport

      + +

      The document.viewport namespace contains methods that return information +about the viewport — the rectangle that represents the portion of a web +page within view. In other words, it's the browser window minus all chrome.

      +
    • +
    +
    +
    + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Class properties

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/dom/document/loaded/index.html b/doc/dom/document/loaded/index.html new file mode 100644 index 000000000..317bd4773 --- /dev/null +++ b/doc/dom/document/loaded/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | document.loaded + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property document.loaded +

    + + + + +
    +
    +
    +
    +
    +
    document.loaded → Boolean
    + + +

    Whether the full DOM tree is ready for manipulation.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/observe/index.html b/doc/dom/document/observe/index.html new file mode 100644 index 000000000..2ff384fdd --- /dev/null +++ b/doc/dom/document/observe/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | document.observe + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.observe +

    + + + + +
    +
    +
    +
    +
    +
    document.observe(eventName, handler) → Element
    + + +

    Listens for the given event over the entire document. Can also be used +for listening to "dom:loaded" event.

    + +

    document.observe is the document-wide version of Element#observe. +Using document.observe is equivalent to +Event.observe(document, eventName, handler).

    + +
    The "dom:loaded" event
    + +

    One really useful event generated by Prototype that you might want to +observe on the document is "dom:loaded". On supporting browsers it +fires on DOMContentLoaded and on unsupporting browsers it simulates it +using smart workarounds. If you used window.onload before you might +want to switch to dom:loaded because it will fire immediately after +the HTML document is fully loaded, but before images on the page are +fully loaded. The load event on window only fires after all page +images are loaded, making it unsuitable for some initialization purposes +like hiding page elements (so they can be shown later).

    + +
    Example
    + +
    document.observe("dom:loaded", function() {
    +  // initially hide all containers for tab content
    +  $$('div.tabcontent').invoke('hide');
    +});
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/stopobserving/index.html b/doc/dom/document/stopobserving/index.html new file mode 100644 index 000000000..94aa33942 --- /dev/null +++ b/doc/dom/document/stopobserving/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | document.stopObserving + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.stopObserving +

    + + + + +
    +
    +
    +
    +
    +
    document.stopObserving([eventName[, handler]]) → Element
    + + +

    Unregisters an event handler from the document.

    + +

    document.stopObserving is the document-wide version of +Element.stopObserving.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/viewport/getdimensions/index.html b/doc/dom/document/viewport/getdimensions/index.html new file mode 100644 index 000000000..bf7e45693 --- /dev/null +++ b/doc/dom/document/viewport/getdimensions/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport.getDimensions + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.viewport.getDimensions +

    + + + + +
    +
    +
    +
    +
    +
    document.viewport.getDimensions() → Object
    + + +

    Returns an object containing viewport dimensions in the form +{ width: Number, height: Number }.

    + +

    The viewport is the subset of the browser window that a page occupies +— the "usable" space in a browser window.

    + +
    Example
    + +
    document.viewport.getDimensions();
    +//-> { width: 776, height: 580 }
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/viewport/getheight/index.html b/doc/dom/document/viewport/getheight/index.html new file mode 100644 index 000000000..b3eb9fbc0 --- /dev/null +++ b/doc/dom/document/viewport/getheight/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport.getHeight + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.viewport.getHeight +

    + + + + +
    +
    +
    +
    +
    +
    document.viewport.getHeight() → Number
    + + +

    Returns the height of the viewport.

    + +

    Equivalent to document.viewport.getDimensions().height.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/viewport/getscrolloffsets/index.html b/doc/dom/document/viewport/getscrolloffsets/index.html new file mode 100644 index 000000000..c57112f78 --- /dev/null +++ b/doc/dom/document/viewport/getscrolloffsets/index.html @@ -0,0 +1,157 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport.getScrollOffsets + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.viewport.getScrollOffsets +

    + + + + +
    +
    +
    +
    +
    +
    document.viewport.getScrollOffsets() → Array
    + + +

    Returns the viewport's horizontal and vertical scroll offsets.

    + +

    Returns an array in the form of [leftValue, topValue]. Also accessible +as properties: { left: leftValue, top: topValue }.

    + +
    Examples
    + +
    document.viewport.getScrollOffsets();
    +//-> { left: 0, top: 0 }
    + window.scrollTo(0, 120);
    +document.viewport.getScrollOffsets();
    +//-> { left: 0, top: 120 }
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/viewport/getwidth/index.html b/doc/dom/document/viewport/getwidth/index.html new file mode 100644 index 000000000..4a1598990 --- /dev/null +++ b/doc/dom/document/viewport/getwidth/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport.getWidth + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method document.viewport.getWidth +

    + + + + +
    +
    +
    +
    +
    +
    document.viewport.getWidth() → Number
    + + +

    Returns the width of the viewport.

    + +

    Equivalent to calling document.viewport.getDimensions().width.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/document/viewport/index.html b/doc/dom/document/viewport/index.html new file mode 100644 index 000000000..9f7a4ca51 --- /dev/null +++ b/doc/dom/document/viewport/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | document.viewport + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace document.viewport +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    The document.viewport namespace contains methods that return information +about the viewport — the rectangle that represents the portion of a web +page within view. In other words, it's the browser window minus all chrome.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/dom/dollar/index.html b/doc/dom/dollar/index.html new file mode 100644 index 000000000..c85e6a9f0 --- /dev/null +++ b/doc/dom/dollar/index.html @@ -0,0 +1,202 @@ + + + + + Prototype v1.7_rc1 API documentation | $ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $ +

    + + + + +
    +
    +
    +
    +
    +
    $(id) → Element
    $(id...) → [Element…]
    +
      +
    • + id + (String | Element) + – A DOM node or a string that references a node's ID. +
    • +
    + + +

    If provided with a string, returns the element in the document with +matching ID; otherwise returns the passed element.

    + +

    Takes in an arbitrary number of arguments. Returns one Element if +given one argument; otherwise returns an Array of Elements.

    + +

    All elements returned by the function are "extended" with Element +instance methods.

    + +
    More Information
    + +

    The $ function is the cornerstone of Prototype. Not only does it +provide a handy alias for document.getElementById, it also lets you pass +indifferently IDs (strings) or DOM node references to your functions:

    + +
    function foo(element) {
    +    element = $(element);
    +    //  rest of the function...
    +}
    +
    +
    + +

    Code written this way is flexible — you can pass it the ID of the element +or the element itself without any type sniffing.

    + +

    Invoking it with only one argument returns the Element, while invoking it +with multiple arguments returns an Array of Elements (and this +works recursively: if you're twisted, you could pass it an array +containing some arrays, and so forth). As this is dependent on +getElementById, W3C specs +apply: nonexistent IDs will yield null and IDs present multiple times in +the DOM will yield erratic results. *If you're assigning the same ID to +multiple elements, you're doing it wrong!*

    + +

    The function also extends every returned element with Element.extend +so you can use Prototype's DOM extensions on it. In the following code, +the two lines are equivalent. However, the second one feels significantly +more object-oriented:

    + +
    // Note quite OOP-like...
    +Element.hide('itemId');
    +// A cleaner feel, thanks to guaranted extension
    +$('itemId').hide();
    +
    +
    + +

    However, when using iterators, leveraging the $ function makes for +more elegant, more concise, and also more efficient code:

    + +
    ['item1', 'item2', 'item3'].each(Element.hide);
    +// The better way:
    +$('item1', 'item2', 'item3').invoke('hide');
    +
    +
    + +

    See How Prototype extends the DOM +for more info.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/dollardollar/index.html b/doc/dom/dollardollar/index.html new file mode 100644 index 000000000..f4abf0ae0 --- /dev/null +++ b/doc/dom/dollardollar/index.html @@ -0,0 +1,223 @@ + + + + + Prototype v1.7_rc1 API documentation | $$ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $$ +

    + + + + +
    +
    +
    +
    +
    +
    $$(cssRule...) → [Element…]
    + + +

    Takes an arbitrary number of CSS selectors (strings) and returns a document-order +array of extended DOM elements that match any of them.

    + +

    Sometimes the usual tools from your DOM arsenal -- document.getElementById encapsulated +by $, getElementsByTagName and even Prototype's very own getElementsByClassName +extensions -- just aren't enough to quickly find elements or collections of elements. +If you know the DOM tree structure, you can simply resort to CSS selectors to get +the job done.

    + +
    Quick examples
    + +
    $$('div');
    +// -> all DIVs in the document. Same as document.getElementsByTagName('div').
    +// Nice addition, the elements you're getting back are already extended!
    + $$('#contents');
    +// -> same as $('contents'), only it returns an array anyway (even though IDs must
    +// be unique within a document).
    + $$('li.faux');
    +// -> all LI elements with class 'faux'
    +
    +
    + +

    The $$ function searches the entire document. For selector queries on more specific +sections of a document, use Element.select.

    + +
    Supported CSS syntax
    + +

    The $$ function does not rely on the browser's internal CSS parsing capabilities +(otherwise, we'd be in cross-browser trouble...), and therefore offers a consistent +set of selectors across all supported browsers.

    + +
    Supported in v1.5.0
    + +
      +
    • Type selector: tag names, as in div.
    • +
    • Descendant selector: the space(s) between other selectors, as in #a li.
    • +
    • Attribute selectors: the full CSS 2.1 set of [attr], [attr=value], [attr~=value] +and [attr|=value]. It also supports [attr!=value]. If the value you're matching +against includes a space, be sure to enclose the value in quotation marks ([title="Hello World!"]).
    • +
    • Class selector: CSS class names, as in .highlighted or .example.wrong.
    • +
    • ID selector: as in #item1.
    • +
    + +
    Supported from v1.5.1
    + +

    Virtually all of CSS3 +is supported, with the exception of pseudo-elements (like ::first-letter) and some +pseudo-classes (like :hover). Some examples of new selectors that can be used in 1.5.1:

    + +
      +
    • Child selector: selects immediate descendants, as in #a > li.
    • +
    • Attribute selectors: all attribute operators are supported, including ~= (matches +part of a space-delimited attribute value, like rel or class); ^= (matches the +beginning of a value); $= (matches the end of a value); and *= (matches any part +of the value).
    • +
    • The :not pseudo-class, as in #a *:not(li) (matches all descendants of #a that +aren't LIs).
    • +
    • All the :nth, :first, and :last pseudo-classes. Examples include tr:nth-child(even) +(all even table rows), li:first-child (the first item in any list), or p:nth-last-of-type(3) +(the third-to-last paragraph on the page).
    • +
    • The :empty pseudo-class (for selecting elements without children or text content).
    • +
    • The :enabled, :disabled, and :checked pseudo-classes (for use with form controls).
    • +
    + +
    Examples
    + +
    $$('#contents a[rel]');
    +// -> all links inside the element of ID "contents" with a rel attribute
    + $$('a[href="#"]');
    +// -> all links with a href attribute of value "#" (eyeew!)
    + $$('#navbar a', '#sidebar a');
    +// -> all links within the elements of ID "navbar" or "sidebar"
    +
    +
    + +

    With version 1.5.1 and above you can do various types of advanced selectors:

    + +
    $$('a:not([rel~=nofollow])');
    +// -> all links, excluding those whose rel attribute contains the word "nofollow"
    + $$('table tbody > tr:nth-child(even)');
    +// -> all even rows within all table bodies
    + $$('div:empty');
    +// -> all DIVs without content (i.e., whitespace-only)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/dollarf/index.html b/doc/dom/dollarf/index.html new file mode 100644 index 000000000..b906323c6 --- /dev/null +++ b/doc/dom/dollarf/index.html @@ -0,0 +1,140 @@ + + + + + Prototype v1.7_rc1 API documentation | $F + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $F +

    + + + + +
    +
    +
    +
    +
    +
    $F(element) → String | Array
    + + +

    Returns the value of a form control. This is a convenience alias of +Form.Element.getValue. Refer to it for full details.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/absolutize/index.html b/doc/dom/element/absolutize/index.html new file mode 100644 index 000000000..1649cb2d7 --- /dev/null +++ b/doc/dom/element/absolutize/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.absolutize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.absolutize +

    + + + + +
    +
    +
    +
    +
    +
    Element.absolutize(element) → Element
    + + +

    Turns element into an absolutely-positioned element without +changing its position in the page layout.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/addclassname/index.html b/doc/dom/element/addclassname/index.html new file mode 100644 index 000000000..0ad07f90a --- /dev/null +++ b/doc/dom/element/addclassname/index.html @@ -0,0 +1,322 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.addClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.addClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element.addClassName(element, className) → Element
    +
      +
    • + className + (String) + – The class name to add. +
    • +
    + + +

    Adds the given CSS class to element.

    + +
    Example
    + +

    Assuming this HTML:

    + +
    <div id="mutsu" class="apple fruit"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').className;
    +// -> 'apple fruit'
    +$('mutsu').addClassName('food');
    +$('mutsu').className;
    +// -> 'apple fruit food'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/addmethods/index.html b/doc/dom/element/addmethods/index.html new file mode 100644 index 000000000..96a3e5bbf --- /dev/null +++ b/doc/dom/element/addmethods/index.html @@ -0,0 +1,438 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.addMethods + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.addMethods +

    + + + + +
    +
    +
    +
    +
    +
    Element.addMethods(methods) → undefined
    Element.addMethods(tagName, methods) → undefined
    +
      +
    • + tagName + (String) + – (Optional) The name of the HTML tag for which the methods should be available; if not given, all HTML elements will have the new methods. +
    • +
    • + methods + (Object) + – A hash of methods to add. +
    • +
    + + +

    Element.addMethods makes it possible to mix your own methods into the +Element object and extended element instances (all of them, or only ones +with the given HTML tag if you specify tagName).

    + +

    You define the methods in a hash that you provide to Element.addMethods. +Here's an example adding two methods:

    + +
    Element.addMethods({
    +   // myOwnMethod: Do something cool with the element
    +  myOwnMethod: function(element) {
    +    if (!(element = $(element))) return;
    +    // ...do smething with 'element'...
    +    return element;
    +  },
    +   // wrap: Wrap the element in a new element using the given tag
    +  wrap: function(element, tagName) {
    +    var wrapper;
    +    if (!(element = $(element))) return;
    +    wrapper = new Element(tagName);
    +    element.parentNode.replaceChild(wrapper, element);
    +    wrapper.appendChild(element);
    +    return wrapper;
    +  }
    + });
    +
    +
    + +

    Once added, those can be used either via Element:

    + +
    // Wrap the element with the ID 'foo' in a div
    +Element.wrap('foo', 'div');
    +
    +
    + +

    ...or as instance methods of extended elements:

    + +
    // Wrap the element with the ID 'foo' in a div
    +$('foo').wrap('div');
    +
    +
    + +

    Note the following requirements and conventions for methods added to +Element:

    + +
      +
    • The first argument is always an element or ID, by convention this +argument is called element.
    • +
    • The method passes the element argument through $ and typically +returns if the result is undefined.
    • +
    • Barring a good reason to return something else, the method returns the +extended element to enable chaining.
    • +
    + +

    Our myOwnMethod method above returns the element because it doesn't have +a good reason to return anything else. Our wrap method returns the +wrapper, because that makes more sense for that method.

    + +
    Extending only specific elements
    + +

    If you call Element.addMethods with two arguments, it will apply the +methods only to elements with the given HTML tag:

    + +
    Element.addMethods('DIV', my_div_methods);
    +// the given methods are now available on DIV elements, but not others
    +
    +
    + +

    You can also pass an Array of tag names as the first argument:

    + +
    Element.addMethods(['DIV', 'SPAN'], my_additional_methods);
    +// DIV and SPAN now both have the given methods
    +
    +
    + +

    (Tag names in the first argument are not case sensitive.)

    + +

    Note: Element.addMethods has built-in security which prevents you from +overriding native element methods or properties (like getAttribute or +innerHTML), but nothing prevents you from overriding one of Prototype's +methods. Prototype uses a lot of its methods internally; overriding its +methods is best avoided or at least done only with great care.

    + +
    Example 1
    + +

    Our wrap method earlier was a complete example. For instance, given this +paragraph:

    + +
    <p id="first">Some content...</p>
    +
    +
    + +

    ...we might wrap it in a div:

    + +
    $('first').wrap('div');
    +
    +
    + +

    ...or perhaps wrap it and apply some style to the div as well:

    + +
    $('first').wrap('div').setStyle({
    +  backgroundImage: 'url(images/rounded-corner-top-left.png) top left'
    +});
    +
    +
    + +
    Example 2
    + +

    We can add a method to elements that makes it a bit easier to update them +via Ajax.Updater:

    + +
    Element.addMethods({
    +  ajaxUpdate: function(element, url, options) {
    +    if (!(element = $(element))) return;
    +    element.update('<img src="/images/spinner.gif" alt="Loading...">');
    +    options = options || {};
    +    options.onFailure = options.onFailure || defaultFailureHandler.curry(element);
    +    new Ajax.Updater(element, url, options);
    +    return element;
    +  }
    +});
    +
    +
    + +

    Now we can update an element via an Ajax call much more concisely than +before:

    + +
    $('foo').ajaxUpdate('/new/content');
    +
    +
    + +

    That will use Ajax.Updater to load new content into the 'foo' element, +showing a spinner while the call is in progress. It even applies a default +failure handler (since we didn't supply one).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/adjacent/index.html b/doc/dom/element/adjacent/index.html new file mode 100644 index 000000000..505374ace --- /dev/null +++ b/doc/dom/element/adjacent/index.html @@ -0,0 +1,331 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.adjacent + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.adjacent +

    + + + + +
    +
    +
    +
    +
    +
    Element.adjacent(element, selector...) → [Element…]
    +
      +
    • + selector + (String) + – A CSS selector. +
    • +
    + + +

    Finds all siblings of the current element that match the given +selector(s). If you provide multiple selectors, siblings matching any +of the selectors are included. If a sibling matches multiple selectors, +it is only included once. The order of the returned array is not defined.

    + +
    Example
    + +

    Assuming this list:

    + +
    <ul id="cities">
    +  <li class="us" id="nyc">New York</li>
    +  <li class="uk" id="lon">London</li>
    +  <li class="us" id="chi">Chicago</li>
    +  <li class="jp" id="tok">Tokyo</li>
    +  <li class="us" id="la">Los Angeles</li>
    +  <li class="us" id="aus">Austin</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('nyc').adjacent('li.us');
    +// -> [li#chi, li#la, li#aus]
    +$('nyc').adjacent('li.uk', 'li.jp');
    +// -> [li#lon, li#tok]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/ancestors/index.html b/doc/dom/element/ancestors/index.html new file mode 100644 index 000000000..36b7a02b5 --- /dev/null +++ b/doc/dom/element/ancestors/index.html @@ -0,0 +1,327 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.ancestors + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.ancestors +

    + + + + +
    +
    +
    +
    +
    +
    Element.ancestors(element) → [Element…]
    + + +

    Collects all of element's ancestor elements and returns them as an +array of extended elements.

    + +

    The returned array's first element is element's direct ancestor (its +parentNode), the second one is its grandparent, and so on until the +<html> element is reached. <html> will always be the last member of +the array. Calling ancestors on the <html> element will return an +empty array.

    + +
    Example
    + +

    Assuming:

    + +
    <html>
    +[...]
    +  <body>
    +    <div id="father">
    +      <div id="kid">
    +      </div>
    +    </div>
    +  </body>
    +</html>
    +
    +
    + +

    Then:

    + +
    $('kid').ancestors();
    +// -> [div#father, body, html]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/childelements/index.html b/doc/dom/element/childelements/index.html new file mode 100644 index 000000000..3146d279e --- /dev/null +++ b/doc/dom/element/childelements/index.html @@ -0,0 +1,328 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.childElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.childElements +

    + + + + +
    +
    +
    +
    +
    +
    Element.childElements(element) → [Element…]
    + + +

    Collects all of the element's children and returns them as an array of +Element.extended elements, in document order. The first +entry in the array is the topmost child of element, the next is the +child after that, etc.

    + +

    Like all of Prototype's DOM traversal methods, Element.childElements +ignores text nodes and returns element nodes only.

    + +
    Example
    + +

    Assuming:

    + +
    <div id="australopithecus">
    +  Some text in a text node
    +  <div id="homo-erectus">
    +    <div id="homo-neanderthalensis"></div>
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('australopithecus').childElements();
    +// -> [div#homo-erectus]
    + $('homo-erectus').childElements();
    +// -> [div#homo-neanderthalensis, div#homo-sapiens]
    + $('homo-sapiens').childElements();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/classnames/index.html b/doc/dom/element/classnames/index.html new file mode 100644 index 000000000..1b68d0fbe --- /dev/null +++ b/doc/dom/element/classnames/index.html @@ -0,0 +1,303 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.classNames + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Element.classNames +

    + + + + +
    +
    +
    +
    +
    +
    Element.classNames(element) → [String…]
    + + +

    Returns a new instance of Element.ClassNames, an Enumerable +object used to read and write CSS class names of element.

    + +

    Deprecated, please see Element.addClassName, +Element.removeClassName, and Element.hasClassName. If you want +an array of classnames, you can use $w(element.className).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/cleanwhitespace/index.html b/doc/dom/element/cleanwhitespace/index.html new file mode 100644 index 000000000..a181c749f --- /dev/null +++ b/doc/dom/element/cleanwhitespace/index.html @@ -0,0 +1,339 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.cleanWhitespace + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.cleanWhitespace +

    + + + + +
    +
    +
    +
    +
    +
    Element.cleanWhitespace(element) → Element
    + + +

    Removes all of element's child text nodes that contain only +whitespace. Returns element.

    + +

    This can be very useful when using standard properties like nextSibling, +previousSibling, firstChild or lastChild to walk the DOM. Usually +you'd only do that if you are interested in all of the DOM nodes, not +just Elements (since if you just need to traverse the Elements in the +DOM tree, you can use Element.up, Element.down, +Element.next, and Element.previous instead).

    + +

    Example

    + +

    Consider the following HTML snippet:

    + +
    <ul id="apples">
    +  <li>Mutsu</li>
    +  <li>McIntosh</li>
    +  <li>Ida Red</li>
    +</ul>
    +
    +
    + +

    Let's grab what we think is the first list item using the raw DOM +method:

    + +
    var element = $('apples');
    +element.firstChild.innerHTML;
    +// -> undefined
    +
    +
    + +

    It's undefined because the firstChild of the apples element is a +text node containing the whitespace after the end of the ul and before +the first li.

    + +

    If we remove the useless whitespace, then firstChild works as expected:

    + +
    var element = $('apples');
    +element.cleanWhitespace();
    +element.firstChild.innerHTML;
    +// -> 'Mutsu'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/clone/index.html b/doc/dom/element/clone/index.html new file mode 100644 index 000000000..8b0526981 --- /dev/null +++ b/doc/dom/element/clone/index.html @@ -0,0 +1,307 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.clone +

    + + + + +
    +
    +
    +
    +
    +
    Element.clone(element, deep) → Element
    +
      +
    • + deep + (Boolean) + – Whether to clone element's descendants as well. +
    • +
    + + +

    Returns a duplicate of element.

    + +

    A wrapper around DOM Level 2 Node#cloneNode, Element.clone cleans up +any expando properties defined by Prototype.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/cloneposition/index.html b/doc/dom/element/cloneposition/index.html new file mode 100644 index 000000000..1718d92ed --- /dev/null +++ b/doc/dom/element/cloneposition/index.html @@ -0,0 +1,359 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.clonePosition + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.clonePosition +

    + + + + +
    +
    +
    +
    +
    +
    Element.clonePosition(element, source[, options]) → Element
    +
      +
    • + source + (Element | String) + – The source element (or its ID). +
    • +
    • + options + (Object) + – The position fields to clone. +
    • +
    + + +

    Clones the position and/or dimensions of source onto the element as +defined by options, with an optional offset for the left and top +properties.

    + +

    Note that the element will be positioned exactly like source whether or +not it is part of the same CSS containing +block.

    + +
    Options
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDefaultDescription
    setLefttrueClones source's left CSS property onto element.
    setToptrueClones source's top CSS property onto element.
    setWidthtrueClones source's width onto element.
    setHeighttrueClones source's width onto element.
    offsetLeft0Number by which to offset element's left CSS property.
    offsetTop0Number by which to offset element's top CSS property.
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/cumulativeoffset/index.html b/doc/dom/element/cumulativeoffset/index.html new file mode 100644 index 000000000..a0014ec14 --- /dev/null +++ b/doc/dom/element/cumulativeoffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.cumulativeOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.cumulativeOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element.cumulativeOffset(element) → Element.Offset
    + + +

    Returns the offsets of element from the top left corner of the +document.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/cumulativescrolloffset/index.html b/doc/dom/element/cumulativescrolloffset/index.html new file mode 100644 index 000000000..51553d52e --- /dev/null +++ b/doc/dom/element/cumulativescrolloffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.cumulativeScrollOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.cumulativeScrollOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element.cumulativeScrollOffset(element) → Element.Offset
    + + +

    Calculates the cumulative scroll offset of an element in nested +scrolling containers.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/descendantof/index.html b/doc/dom/element/descendantof/index.html new file mode 100644 index 000000000..efeb40118 --- /dev/null +++ b/doc/dom/element/descendantof/index.html @@ -0,0 +1,325 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.descendantOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.descendantOf +

    + + + + +
    +
    +
    +
    +
    +
    Element.descendantOf(element, ancestor) → Boolean
    +
      +
    • + ancestor + (Element | String) + – The element to check against (or its ID). +
    • +
    + + +

    Checks if element is a descendant of ancestor.

    + +
    Example
    + +

    Assuming:

    + +
    <div id="australopithecus">
    +  <div id="homo-erectus">
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('homo-sapiens').descendantOf('australopithecus');
    +// -> true
    + $('homo-erectus').descendantOf('homo-sapiens');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/descendants/index.html b/doc/dom/element/descendants/index.html new file mode 100644 index 000000000..136a1e956 --- /dev/null +++ b/doc/dom/element/descendants/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.descendants + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.descendants +

    + + + + +
    +
    +
    +
    +
    +
    Element.descendants(element) → [Element…]
    + + +

    Collects all of the element's descendants (its children, their children, +etc.) and returns them as an array of extended elements. As with all of +Prototype's DOM traversal methods, only Elements are returned, other +nodes (text nodes, etc.) are skipped.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/down/index.html b/doc/dom/element/down/index.html new file mode 100644 index 000000000..a0cc0d7f8 --- /dev/null +++ b/doc/dom/element/down/index.html @@ -0,0 +1,409 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.down + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.down +

    + + + + +
    +
    +
    +
    +
    +
    Element.down(element[, expression[, index = 0]]) → Element
    Element.down(element[, index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first descendant (or the Nth descendant, if index +is specified) that matches expression. If no expression is +provided, all descendants are considered. If no descendant matches these +criteria, undefined is returned.

    + +
    More information
    + +

    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 +(see Element.extend) allowing chaining:

    + +
    $(element).down(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's first descendant is returned (this +is similar to calling firstChild except Element.down returns an +extended element.

    + +

    If index is defined, element's corresponding descendant is returned. +(This is equivalent to selecting an element from the array of elements +returned by the method Element.descendants.) Note that the first +element has an index of 0.

    + +

    If expression is defined, Element.down will return the first +descendant that matches it. This is a great way to grab the first item in +a list for example (just pass in 'li' as the method's first argument).

    + +

    If both expression and index are defined, Element.down will collect +all the descendants matching the given CSS expression and will return the +one at the specified index.

    + +

    In all of the above cases, if no descendant is found, undefined +will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <ul>
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first descendant of "#fruites":

    + +
    $('fruits').down();
    +// or:
    +$('fruits').down(0);
    +// -> li#apples
    +
    +
    + +

    Get the third descendant of "#fruits":

    + +
    $('fruits').down(3);
    +// -> li#golden-delicious
    +
    +
    + +

    Get the first descendant of "#apples" with the node name "li":

    + +
    $('apples').down('li');
    +// -> li#golden-delicious
    +
    +
    + +

    Get the first descendant of "#apples" with the node name "li" and the +class name "yummy":

    + +
    $('apples').down('li.yummy');
    +// -> li#mutsu
    +
    +
    + +

    Get the second descendant of "#fruits" with the class name "yummy":

    + +
    $('fruits').down('.yummy', 1);
    +// -> li#mcintosh
    +
    +
    + +

    Try to get the ninety-ninth descendant of "#fruits":

    + +
    $('fruits').down(99);
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/empty/index.html b/doc/dom/element/empty/index.html new file mode 100644 index 000000000..8511d201f --- /dev/null +++ b/doc/dom/element/empty/index.html @@ -0,0 +1,308 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.empty + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.empty +

    + + + + +
    +
    +
    +
    +
    +
    Element.empty(element) → Element
    + + +

    Tests whether element is empty (i.e., contains only whitespace).

    + +
    Examples
    + +
    <div id="wallet">     </div>
    +<div id="cart">full!</div>
    + $('wallet').empty();
    +// -> true
    + $('cart').empty();
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/extend/index.html b/doc/dom/element/extend/index.html new file mode 100644 index 000000000..f3801d549 --- /dev/null +++ b/doc/dom/element/extend/index.html @@ -0,0 +1,313 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.extend +

    + + + + +
    +
    +
    +
    +
    +
    Element.extend(element) → Element
    + + +

    Extends the given element instance with all of the Prototype goodness and +syntactic sugar, as well as any extensions added via Element.addMethods. +(If the element instance was already extended, this is a no-op.)

    + +

    You only need to use Element.extend on element instances you've acquired +directly from the DOM; all Prototype methods that return element +instances (such as $, Element.down, etc.) will pre-extend the +element before returning it.

    + +

    Check out "How Prototype extends the +DOM" for more about element +extensions.

    + +
    Details
    + +

    Specifically, Element.extend extends the given instance with the methods +contained in Element.Methods and Element.Methods.Simulated. If element +is an input, textarea, or select element, it will also be extended +with the methods from Form.Element.Methods. If it is a form element, it +will also be extended with the methods from Form.Methods.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/fire/index.html b/doc/dom/element/fire/index.html new file mode 100644 index 000000000..b7c960b1e --- /dev/null +++ b/doc/dom/element/fire/index.html @@ -0,0 +1,336 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.fire + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.fire +

    + + + + +
    +
    +
    +
    +
    +
    Element.fire(element, eventName[, memo[, bubble = true]]) → Event
    + + +

    See Event.fire.

    + +

    Fires a custom event with the current element as its target.

    + +

    Element.fire creates a custom event with the given name, then triggers +it on the given element. The custom event has all the same properties +and methods of native events. Like a native event, it will bubble up +through the DOM unless its propagation is explicitly stopped.

    + +

    The optional second argument will be assigned to the memo property of +the event object so that it can be read by event handlers.

    + +

    Custom events are dispatched synchronously: Element.fire waits until +the event finishes its life cycle, then returns the event itself.

    + +
    Note
    + +

    Element.fire does not support firing native events. All custom event +names must be namespaced (using a colon). This is to avoid custom +event names conflicting with non-standard native DOM events such as +mousewheel and DOMMouseScroll.

    + +
    Examples
    + +
    document.observe("widget:frobbed", function(event) {
    +  console.log("Element with ID (" + event.target.id +
    +   ") frobbed widget #" + event.memo.widgetNumber + ".");
    +});
    + var someNode = $('foo');
    +someNode.fire("widget:frobbed", { widgetNumber: 19 });
    + //-> "Element with ID (foo) frobbed widget #19."
    +
    +
    + +
    Tip
    + +

    Events that have been stopped with Event.stop will have a boolean +stopped property set to true. Since Element.fire returns the custom +event, you can inspect this property to determine whether the event was +stopped.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/firstdescendant/index.html b/doc/dom/element/firstdescendant/index.html new file mode 100644 index 000000000..d8db0d3f1 --- /dev/null +++ b/doc/dom/element/firstdescendant/index.html @@ -0,0 +1,324 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.firstDescendant + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.firstDescendant +

    + + + + +
    +
    +
    +
    +
    +
    Element.firstDescendant(element) → Element
    + + +

    Returns the first child that is an element.

    + +

    This is opposed to the firstChild DOM property, which will return +any node, including text nodes and comment nodes.

    + +
    Examples
    + +
    <div id="australopithecus">
    +  <div id="homo-erectus"><!-- Latin is super -->
    +    <div id="homo-neanderthalensis"></div>
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('australopithecus').firstDescendant();
    +// -> div#homo-herectus
    + // the DOM property returns any first node
    +$('homo-herectus').firstChild;
    +// -> comment node "Latin is super"
    + // this is what we want!
    +$('homo-herectus').firstDescendant();
    +// -> div#homo-neanderthalensis
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getdimensions/index.html b/doc/dom/element/getdimensions/index.html new file mode 100644 index 000000000..2010b1dac --- /dev/null +++ b/doc/dom/element/getdimensions/index.html @@ -0,0 +1,326 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getDimensions + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getDimensions +

    + + + + +
    +
    +
    +
    +
    +
    Element.getDimensions(element) → Object
    + + +

    Finds the computed width and height of element and returns them as +key/value pairs of an object.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    In order to avoid calling the method twice, you should consider caching +the values returned in a variable as shown below. If you only need +element's width or height, consider using Element.getWidth or +Element.getHeight instead.

    + +

    Note that all values are returned as numbers only although they are +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    var dimensions = $('rectangle').getDimensions();
    +// -> {width: 200, height: 100}
    + dimensions.width;
    +// -> 200
    + dimensions.height;
    +// -> 100
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getelementsbyselector/index.html b/doc/dom/element/getelementsbyselector/index.html new file mode 100644 index 000000000..f243b690d --- /dev/null +++ b/doc/dom/element/getelementsbyselector/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getElementsBySelector + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getElementsBySelector +

    + + + + +
    +
    +
    +
    +
    +
    Element.getElementsBySelector(element, selector) → [Element…]
    + + + + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getheight/index.html b/doc/dom/element/getheight/index.html new file mode 100644 index 000000000..3a6cac756 --- /dev/null +++ b/doc/dom/element/getheight/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getHeight + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getHeight +

    + + + + +
    +
    +
    +
    +
    +
    Element.getHeight(element) → Number
    + + +

    Returns the height of element.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    For performance reasons, if you need to query both width and height of +element, you should consider using Element.getDimensions instead.

    + +

    Note that the value returned is a number only although it is +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    $('rectangle').getHeight();
    +// -> 100
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getlayout/index.html b/doc/dom/element/getlayout/index.html new file mode 100644 index 000000000..82d65ba7f --- /dev/null +++ b/doc/dom/element/getlayout/index.html @@ -0,0 +1,305 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getLayout + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getLayout +

    + + + + +
    +
    +
    +
    +
    +
    Element.getLayout(element, preCompute) → Element.Layout
    + + +

    Returns an instance of Element.Layout for measuring an element's +dimensions.

    + +

    Note that this method returns a new Element.Layout object each time +it's called. If you want to take advantage of measurement caching, +retain a reference to one Element.Layout object, rather than calling +Element.getLayout whenever you need a measurement. You should call +Element.getLayout again only when the values in an existing +Element.Layout object have become outdated.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getoffsetparent/index.html b/doc/dom/element/getoffsetparent/index.html new file mode 100644 index 000000000..f29b8d74c --- /dev/null +++ b/doc/dom/element/getoffsetparent/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getOffsetParent + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getOffsetParent +

    + + + + +
    +
    +
    +
    +
    +
    Element.getOffsetParent(element) → Element
    + + +

    Returns element's closest positioned ancestor. If none is found, the +body element is returned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getopacity/index.html b/doc/dom/element/getopacity/index.html new file mode 100644 index 000000000..0423c01c0 --- /dev/null +++ b/doc/dom/element/getopacity/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getOpacity + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getOpacity +

    + + + + +
    +
    +
    +
    +
    +
    Element.getOpacity(element) → String | null
    + + +

    Returns the opacity of the element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getstorage/index.html b/doc/dom/element/getstorage/index.html new file mode 100644 index 000000000..fda1f05dd --- /dev/null +++ b/doc/dom/element/getstorage/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getStorage + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getStorage +

    + + + + +
    +
    +
    +
    +
    +
    Element.getStorage(element) → Hash
    + + +

    Returns the Hash object that stores custom metadata for this element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getstyle/index.html b/doc/dom/element/getstyle/index.html new file mode 100644 index 000000000..509ff4911 --- /dev/null +++ b/doc/dom/element/getstyle/index.html @@ -0,0 +1,354 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getStyle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getStyle +

    + + + + +
    +
    +
    +
    +
    +
    Element.getStyle(element, style) → String | null
    +
      +
    • + style + (String) + – The property name to be retrieved. +
    • +
    + + +

    Returns the given CSS property value of element. The property can be +specified in either its CSS form (font-size) or its camelized form +(fontSize).

    + +

    This method looks up the CSS property of an element whether it was +applied inline or in a stylesheet. It works around browser inconsistencies +regarding float, opacity, which returns a value between 0 +(fully transparent) and 1 (fully opaque), position properties +(left, top, right and bottom) and when getting the dimensions +(width or height) of hidden elements.

    + +
    Examples
    + +
    $(element).getStyle('font-size');
    +// equivalent:
    + $(element).getStyle('fontSize');
    +// -> '12px'
    +
    +
    + +
    Notes
    + +

    Internet Explorer returns literal values while other browsers return +computed values.

    + +

    Consider the following HTML snippet:

    + +
    <style>
    +  #test {
    +    font-size: 12px;
    +    margin-left: 1em;
    +  }
    +</style>
    +<div id="test"></div>
    +
    +
    + +

    Then:

    + +
    $('test').getStyle('margin-left');
    +// -> '1em' in Internet Explorer,
    +// -> '12px' elsewhere.
    +
    +
    + +

    Safari returns null for any non-inline property if the element is +hidden (has display set to 'none').

    + +

    Not all CSS shorthand properties are supported. You may only use the CSS +properties described in the +Document Object Model (DOM) Level 2 Style Specification.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/getwidth/index.html b/doc/dom/element/getwidth/index.html new file mode 100644 index 000000000..b82f9ccbb --- /dev/null +++ b/doc/dom/element/getwidth/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.getWidth + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.getWidth +

    + + + + +
    +
    +
    +
    +
    +
    Element.getWidth(element) → Number
    + + +

    Returns the width of element.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    For performance reasons, if you need to query both width and height of +element, you should consider using Element.getDimensions instead.

    + +

    Note that the value returned is a number only although it is +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    $('rectangle').getWidth();
    +// -> 200
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/hasattribute/index.html b/doc/dom/element/hasattribute/index.html new file mode 100644 index 000000000..6540feb38 --- /dev/null +++ b/doc/dom/element/hasattribute/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.hasAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.hasAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element.hasAttribute(element, attribute) → Boolean
    + + +

    Simulates the standard compliant DOM method +hasAttribute +for browsers missing it (Internet Explorer 6 and 7).

    + +
    Example
    + +
    <a id="link" href="http://prototypejs.org">Prototype</a>
    +
    +
    + +

    Then:

    + +
    $('link').hasAttribute('href');
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/hasclassname/index.html b/doc/dom/element/hasclassname/index.html new file mode 100644 index 000000000..623620687 --- /dev/null +++ b/doc/dom/element/hasclassname/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.hasClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.hasClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element.hasClassName(element, className) → Boolean
    + + +

    Checks for the presence of CSS class className on element.

    + +
    Examples
    + +
    <div id="mutsu" class="apple fruit food"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').hasClassName('fruit');
    +// -> true
    + $('mutsu').hasClassName('vegetable');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/hide/index.html b/doc/dom/element/hide/index.html new file mode 100644 index 000000000..49fa9da21 --- /dev/null +++ b/doc/dom/element/hide/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.hide + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.hide +

    + + + + +
    +
    +
    +
    +
    +
    Element.hide(element) → Element
    + + +

    Sets display: none on element. Returns element.

    + +
    Examples
    + +

    Hide a single element:

    + +
    <div id="error-message"></div>
    + $('error-message').hide();
    +// -> Element (and hides div#error-message)
    +
    +
    + +

    Hide multiple elements using Enumerable#each:

    + +
    ['content', 'navigation', 'footer'].each(Element.hide);
    +// -> ['content', 'navigation', 'footer']
    +
    +
    + +

    Hide multiple elements using Enumerable#invoke:

    + +
    $('content', 'navigation', 'footer').invoke('hide');
    +// -> [Element, Element, Element]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/identify/index.html b/doc/dom/element/identify/index.html new file mode 100644 index 000000000..18f00a764 --- /dev/null +++ b/doc/dom/element/identify/index.html @@ -0,0 +1,327 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.identify + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.identify +

    + + + + +
    +
    +
    +
    +
    +
    Element.identify(element) → String
    + + +

    Returns element's ID. If element does not have an ID, one is +generated, assigned to element, and returned.

    + +
    Examples
    + +

    Original HTML:

    + +
      <ul>
    +    <li id="apple">apple</li>
    +    <li>orange</li>
    +  </ul>
    +
    +
    + +

    JavaScript:

    + +
      $('apple').identify();
    +  // -> 'apple'
    +   $('apple').next().identify();
    +  // -> 'anonymous_element_1'
    +
    +
    + +

    Resulting HTML:

    + +
      <ul>
    +    <li id="apple">apple</li>
    +    <li id="anonymous_element_1">orange</li>
    +  </ul>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/immediatedescendants/index.html b/doc/dom/element/immediatedescendants/index.html new file mode 100644 index 000000000..5beb2d2da --- /dev/null +++ b/doc/dom/element/immediatedescendants/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.immediateDescendants + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Element.immediateDescendants +

    + + + + +
    +
    +
    +
    +
    +
    Element.immediateDescendants(element) → [Element…]
    + + +

    This method is deprecated, please see Element.childElements.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/index.html b/doc/dom/element/index.html new file mode 100644 index 000000000..9ef90867d --- /dev/null +++ b/doc/dom/element/index.html @@ -0,0 +1,695 @@ + + + + + Prototype v1.7_rc1 API documentation | Element + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Element +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    The Element object provides a variety of powerful DOM methods for +interacting with DOM elements — creating them, updating them, +traversing them, etc. You can access these either as methods of Element +itself, passing in the element to work with as the first argument, or as +methods on extended element instances:

    + +
    // Using Element:
    +Element.addClassName('target', 'highlighted');
    + // Using an extended element instance:
    +$('target').addClassName('highlighted');
    +
    +
    + +

    Element is also a constructor for building element instances from scratch, +see new Element for details.

    + +

    Most Element methods return the element instance, so that you can chain +them easily:

    + +
    $('message').addClassName('read').update('I read this message!');
    +
    +
    + +
    More Information
    + +

    For more information about extended elements, check out "How Prototype +extends the DOM", which will walk +you through the inner workings of Prototype's DOM extension mechanism.

    +
    +
    + + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Element.Layout

      + +

      A set of key/value pairs representing measurements of various +dimensions of an element.

      +
    • +
    • +

      Element.Offset

      + +

      A representation of the top- and left-offsets of an element relative to +another.

      +
    • +
    +
    +
    + + + + +
    +
    +

    Includes

    +
    + +
    + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Element

    +
    +
    + + + + + + + + +
    + + + +
    + + diff --git a/doc/dom/element/insert/index.html b/doc/dom/element/insert/index.html new file mode 100644 index 000000000..73a4eef62 --- /dev/null +++ b/doc/dom/element/insert/index.html @@ -0,0 +1,352 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.insert + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.insert +

    + + + + +
    +
    +
    +
    +
    +
    Element.insert(element, content) → Element
    + + + +

    Inserts content above, below, at the top, and/or at the bottom of +the given element, depending on the option(s) given.

    + +

    insert accepts content in any of these forms:

    + +
      +
    • String: A string of HTML to be parsed and rendered
    • +
    • Element: An Element instance to insert
    • +
    • ...any object with a toElement method: The method is called and the resulting element used
    • +
    • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
    • +
    + +

    The content argument can be the content to insert, in which case the +implied insertion point is bottom, or an object that specifies one or +more insertion points (e.g., { bottom: "foo", top: "bar" }).

    + +

    Accepted insertion points are:

    + +
      +
    • before (as element's previous sibling)
    • +
    • after (as element's next sibling)
    • +
    • top (as element's first child)
    • +
    • bottom (as element's last child)
    • +
    + +

    Note that if the inserted HTML contains any <script> tag, these will be +automatically evaluated after the insertion (insert internally calls +String.evalScripts when inserting HTML).

    + +
    Examples
    + +

    Insert the given HTML at the bottom of the element (using the default):

    + +
    $('myelement').insert("<p>HTML to append</p>");
    + $('myelement').insert({
    +  top: new Element('img', {src: 'logo.png'})
    +});
    +
    +
    + +

    Put hrs before and after the element:

    + +
    $('myelement').insert({
    +  before: "<hr>",
    +  after: "<hr>"
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/inspect/index.html b/doc/dom/element/inspect/index.html new file mode 100644 index 000000000..f6bc45178 --- /dev/null +++ b/doc/dom/element/inspect/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.inspect +

    + + + + +
    +
    +
    +
    +
    +
    Element.inspect(element) → String
    + + +

    Returns the debug-oriented string representation of element.

    + +

    For more information on inspect methods, see Object.inspect.

    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu" class="yummy apple">Mutsu</li>
    +  <li id="mcintosh" class="yummy">McIntosh</li>
    +  <li></li>
    +</ul>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('golden-delicious').inspect();
    +// -> '<li id="golden-delicious">'
    + $('mutsu').inspect();
    +// -> '<li id="mutsu" class="yummy apple">'
    + $('mutsu').next().inspect();
    +// -> '<li>'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/layout/composite_properties/index.html b/doc/dom/element/layout/composite_properties/index.html new file mode 100644 index 000000000..d64305b1f --- /dev/null +++ b/doc/dom/element/layout/composite_properties/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout.COMPOSITE_PROPERTIES + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constant Element.Layout.COMPOSITE_PROPERTIES +

    + + + + +
    +
    +
    +
    +
    +
    + + +

    A list of all composite properties. Composite properties don't map +directly to CSS properties — they're combinations of other +properties.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/layout/index.html b/doc/dom/element/layout/index.html new file mode 100644 index 000000000..e9043cc38 --- /dev/null +++ b/doc/dom/element/layout/index.html @@ -0,0 +1,446 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Element.Layout +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A set of key/value pairs representing measurements of various +dimensions of an element.

    + +

    Overview

    + +

    The Element.Layout class is a specialized way to measure elements. +It helps mitigate:

    + +
      +
    • The convoluted steps often needed to get common measurements for +elements.
    • +
    • The tendency of browsers to report measurements in non-pixel units.
    • +
    • The quirks that lead some browsers to report inaccurate measurements.
    • +
    • The difficulty of measuring elements that are hidden.
    • +
    + +

    Usage

    + +

    Instantiate an Element.Layout class by passing an element into the +constructor:

    + +
    var layout = new Element.Layout(someElement);
    +
    +
    + +

    You can also use Element.getLayout, if you prefer.

    + +

    Once you have a layout object, retrieve properties using Hash's +familiar get and set syntax.

    + +
    layout.get('width');  //-> 400
    +layout.get('top');    //-> 180
    +
    +
    + +

    The following are the CSS-related properties that can be retrieved. +Nearly all of them map directly to their property names in CSS. (The +only exception is for borders — e.g., border-width instead of +border-left-width.)

    + +
      +
    • height
    • +
    • width
    • +
    • top
    • +
    • left
    • +
    • right
    • +
    • bottom
    • +
    • border-left
    • +
    • border-right
    • +
    • border-top
    • +
    • border-bottom
    • +
    • padding-left
    • +
    • padding-right
    • +
    • padding-top
    • +
    • padding-bottom
    • +
    • margin-top
    • +
    • margin-bottom
    • +
    • margin-left
    • +
    • margin-right
    • +
    + +

    In addition, these "composite" properties can be retrieved:

    + +
      +
    • padding-box-width (width of the content area, from the beginning of +the left padding to the end of the right padding)
    • +
    • padding-box-height (height of the content area, from the beginning +of the top padding to the end of the bottom padding)
    • +
    • border-box-width (width of the content area, from the outer edge of +the left border to the outer edge of the right border)
    • +
    • border-box-height (height of the content area, from the outer edge +of the top border to the outer edge of the bottom border)
    • +
    • margin-box-width (width of the content area, from the beginning of +the left margin to the end of the right margin)
    • +
    • margin-box-height (height of the content area, from the beginning +of the top margin to the end of the bottom margin)
    • +
    + +

    Caching

    + +

    Because these properties can be costly to retrieve, Element.Layout +behaves differently from an ordinary Hash.

    + +

    First: by default, values are "lazy-loaded" — they aren't computed +until they're retrieved. To measure all properties at once, pass +a second argument into the constructor:

    + +
    var layout = new Element.Layout(someElement, true);
    +
    +
    + +

    Second: once a particular value is computed, it's cached. Asking for +the same property again will return the original value without +re-computation. This means that **an instance of Element.Layout +becomes stale when the element's dimensions change**. When this +happens, obtain a new instance.

    + +

    Hidden elements

    + +

    Because it's a common case to want the dimensions of a hidden element +(e.g., for animations), it's possible to measure elements that are +hidden with display: none.

    + +

    However, **it's only possible to measure a hidden element if its parent +is visible**. If its parent (or any other ancestor) is hidden, any +width and height measurements will return 0, as will measurements for +top|bottom|left|right.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Constants

    +
    + +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/dom/element/layout/new/index.html b/doc/dom/element/layout/new/index.html new file mode 100644 index 000000000..6bd2a3cf5 --- /dev/null +++ b/doc/dom/element/layout/new/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.7_rc1 API documentation | new Element.Layout + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Element.Layout +

    + + + + +
    +
    +
    +
    +
    +
    new(element[, preCompute])
    +
      +
    • + element + (Element) + – The element to be measured. +
    • +
    • + preCompute + (Boolean) + – Whether to compute all values at once. +
    • +
    + + +

    Declare a new layout hash.

    + +

    The preCompute argument determines whether measurements will be +lazy-loaded or not. If you plan to use many different measurements, +it's often more performant to pre-compute, as it minimizes the +amount of overhead needed to measure. If you need only one or two +measurements, it's probably not worth it.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/layout/properties/index.html b/doc/dom/element/layout/properties/index.html new file mode 100644 index 000000000..d6e7d6956 --- /dev/null +++ b/doc/dom/element/layout/properties/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout.PROPERTIES + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constant Element.Layout.PROPERTIES +

    + + + + +
    +
    +
    +
    +
    +
    + + +

    A list of all measurable properties.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/layout/prototype/get/index.html b/doc/dom/element/layout/prototype/get/index.html new file mode 100644 index 000000000..99164bb58 --- /dev/null +++ b/doc/dom/element/layout/prototype/get/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout#get + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Layout#get +

    + + + + +
    +
    +
    +
    +
    +
    Element.Layout#get(property) → Number
    + + + +

    Retrieve the measurement specified by property. Will throw an error +if the property is invalid.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/layout/prototype/tocss/index.html b/doc/dom/element/layout/prototype/tocss/index.html new file mode 100644 index 000000000..51b61c83a --- /dev/null +++ b/doc/dom/element/layout/prototype/tocss/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Layout#toCSS + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Layout#toCSS +

    + + + + +
    +
    +
    +
    +
    +
    Element.Layout#toCSS([keys...]) → Object
    +
      +
    • + keys + (String) + – A space-separated list of keys to include. +
    • +
    + + +

    Converts the layout hash to a plain object of CSS property/value +pairs, optionally including only the given keys.

    + +

    Keys can be passed into this method as individual arguments _or_ +separated by spaces within a string.

    + +
    // Equivalent statements:
    +someLayout.toCSS('top', 'bottom', 'left', 'right');
    +someLayout.toCSS('top bottom left right');
    +
    +
    + +

    Useful for passing layout properties to Element.setStyle.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/makeclipping/index.html b/doc/dom/element/makeclipping/index.html new file mode 100644 index 000000000..e4ade59e1 --- /dev/null +++ b/doc/dom/element/makeclipping/index.html @@ -0,0 +1,344 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.makeClipping + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.makeClipping +

    + + + + +
    +
    +
    +
    +
    +
    Element.makeClipping(element) → Element
    + + +

    Simulates the poorly-supported CSS clip property by setting element's +overflow value to hidden.

    + +

    To undo clipping, use Element.undoClipping.

    + +

    The visible area is determined by element's width and height.

    + +
    Example
    + +
    <div id="framer">
    +  <img src="/assets/2007/1/14/chairs.jpg" alt="example" />
    +</div>
    +
    +
    + +

    Then:

    + +
    $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +// -> Element
    +
    +
    + +

    Another example:

    + +
    <a id="clipper" href="#">Click me to try it out.</a>
    + <div id="framer">
    +  <img src="/assets/2007/2/24/chairs.jpg" alt="example" />
    +</div>
    + <script type="text/javascript" charset="utf-8">
    +  var Example = {
    +    clip: function(){
    +      $('clipper').update('undo clipping!');
    +      $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +    },
    +    unClip: function(){
    +      $('clipper').update('clip!');
    +      $('framer').undoClipping();
    +    },
    +    toggleClip: function(event){
    +      if($('clipper').innerHTML == 'undo clipping!') Example.unClip();
    +      else Example.clip();
    +      Event.stop(event);
    +    }
    +  };
    +  Event.observe('clipper', 'click', Example.toggleClip);
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/makepositioned/index.html b/doc/dom/element/makepositioned/index.html new file mode 100644 index 000000000..d912d15ff --- /dev/null +++ b/doc/dom/element/makepositioned/index.html @@ -0,0 +1,302 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.makePositioned + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.makePositioned +

    + + + + +
    +
    +
    +
    +
    +
    Element.makePositioned(element) → Element
    + + +

    Allows for the easy creation of a CSS containing block by setting +element's CSS position to relative if its initial position is +either static or undefined.

    + +

    To revert back to element's original CSS position, use +Element.undoPositioned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/match/index.html b/doc/dom/element/match/index.html new file mode 100644 index 000000000..9ee14407b --- /dev/null +++ b/doc/dom/element/match/index.html @@ -0,0 +1,330 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.match +

    + + + + +
    +
    +
    +
    +
    +
    Element.match(element, selector) → boolean
    +
      +
    • + selector + (String) + – A CSS selector. +
    • +
    + + +

    Checks if element matches the given CSS selector.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <ul>
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +  </li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('fruits').match('ul');
    +// -> true
    + $('mcintosh').match('li#mcintosh.yummy');
    +// -> true
    + $('fruits').match('p');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/measure/index.html b/doc/dom/element/measure/index.html new file mode 100644 index 000000000..a48a5c79b --- /dev/null +++ b/doc/dom/element/measure/index.html @@ -0,0 +1,303 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.measure + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.measure +

    + + + + +
    +
    +
    +
    +
    +
    Element.measure(element, property) → Number
    + + +

    Gives the pixel value of element's dimension specified by +property.

    + +

    Useful for one-off measurements of elements. If you find yourself +calling this method frequently over short spans of code, you might want +to call Element.getLayout and operate on the Element.Layout +object itself (thereby taking advantage of measurement caching).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/methods/index.html b/doc/dom/element/methods/index.html new file mode 100644 index 000000000..858bf3386 --- /dev/null +++ b/doc/dom/element/methods/index.html @@ -0,0 +1,313 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Methods + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + mixin Element.Methods +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Element.Methods is a mixin for DOM elements. The methods of this object +are accessed through the $ utility or through the Element object and +shouldn't be accessed directly.

    + +
    Examples
    + +

    Hide the element

    + +
    $(element).hide();
    +
    +
    + +

    Return an Enumerable of all descendant nodes of the element with the id +"article"

    + +
    $('articles').descendants();
    +
    +
    +
    +
    + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/dom/element/new/index.html b/doc/dom/element/new/index.html new file mode 100644 index 000000000..4e120446a --- /dev/null +++ b/doc/dom/element/new/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | new Element + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Element +

    + + + + +
    +
    +
    +
    +
    +
    new(tagName[, attributes])
    +
      +
    • + tagName + (String) + – The name of the HTML element to create. +
    • +
    • + attributes + (Object) + – An optional group of attribute/value pairs to set on the element. +
    • +
    + + +

    Creates an HTML element with tagName as the tag name, optionally with the +given attributes. This can be markedly more concise than working directly +with the DOM methods, and takes advantage of Prototype's workarounds for +various browser issues with certain attributes:

    + +
    Example
    + +
    // The old way:
    +var a = document.createElement('a');
    +a.setAttribute('class', 'foo');
    +a.setAttribute('href', '/foo.html');
    +a.appendChild(document.createTextNode("Next page"));
    + // The new way:
    +var a = new Element('a', {'class': 'foo', href: '/foo.html'}).update("Next page");
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/next/index.html b/doc/dom/element/next/index.html new file mode 100644 index 000000000..94b101e6a --- /dev/null +++ b/doc/dom/element/next/index.html @@ -0,0 +1,411 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.next + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.next +

    + + + + +
    +
    +
    +
    +
    +
    Element.next(element[, expression[, index = 0]]) → Element
    Element.next(element[, index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first following sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all following siblings are considered. If none matches these +criteria, undefined is returned.

    + +
    More information
    + +

    The Element.next method is part of Prototype's ultimate DOM traversal +toolkit (check out Element.up, Element.down and +Element.previous for some more Prototypish niceness). It allows +precise index-based and/or CSS expression-based selection of any of +element's following siblings. (Note that two elements are considered +siblings if they have the same parent, so for example, the head and +body elements are siblings—their parent is the html element.)

    + +

    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 (see +Element.extend) allowing chaining:

    + +
    $(element).down(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's following sibling is returned +(this is similar as calling nextSibling except Element.next returns an +already extended element).

    + +

    If index is defined, element's corresponding following sibling is +returned. (This is equivalent to selecting an element from the array of +elements returned by the method Element.nextSiblings). Note that the +sibling right below element has an index of 0.

    + +

    If expression is defined, Element.next will return the element first +following sibling that matches it.

    + +

    If both expression and index are defined, Element.next will collect +all of element's following siblings matching the given CSS expression +and will return the one at the specified index.

    + +

    In all of the above cases, if no following sibling is found, +undefined will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3 id="title">Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red" class="yummy">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first sibling after "#title":

    + +
    $('title').next();
    +// or:
    +$('title').next(0);
    +// -> ul#list-of-apples
    +
    +
    + +

    Get the second sibling after "#title":

    + +
    $('title').next(1);
    +// -> p#saying
    +
    +
    + +

    Get the first sibling after "#title" with node name "p":

    + +
    $('title').next('p');
    +// -> p#sayings
    +
    +
    + +

    Get the first sibling after "#golden-delicious" with class name "yummy":

    + +
    $('golden-delicious').next('.yummy');
    +// -> li#mcintosh
    +
    +
    + +

    Get the second sibling after "#golden-delicious" with class name "yummy":

    + +
    $('golden-delicious').next('.yummy', 1);
    +// -> li#ida-red
    +
    +
    + +

    Try to get the first sibling after "#ida-red":

    + +
    $('ida-red').next();
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/nextsiblings/index.html b/doc/dom/element/nextsiblings/index.html new file mode 100644 index 000000000..3de5a93cd --- /dev/null +++ b/doc/dom/element/nextsiblings/index.html @@ -0,0 +1,329 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.nextSiblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.nextSiblings +

    + + + + +
    +
    +
    +
    +
    +
    Element.nextSiblings(element) → [Element…]
    + + +

    Collects all of element's next siblings and returns them as an Array +of elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the head and body elements are siblings (their parent is the html +element). Next-siblings are simply the ones which follow element in the +document.

    + +

    The returned Array reflects the siblings order in the document +(e.g. an index of 0 refers to the sibling right below element).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mutsu').nextSiblings();
    +// -> [li#mcintosh, li#ida-red]
    + $('ida-red').nextSiblings();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/observe/index.html b/doc/dom/element/observe/index.html new file mode 100644 index 000000000..40967c0c2 --- /dev/null +++ b/doc/dom/element/observe/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.observe + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.observe +

    + + + + +
    +
    +
    +
    +
    +
    Element.observe(element, eventName, handler) → Element
    + + +

    See Event.observe.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/offset/index.html b/doc/dom/element/offset/index.html new file mode 100644 index 000000000..8c5aeb681 --- /dev/null +++ b/doc/dom/element/offset/index.html @@ -0,0 +1,332 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Element.Offset +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A representation of the top- and left-offsets of an element relative to +another.

    + +

    All methods that compute offsets return an instance of Element.Offset.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/dom/element/offset/new/index.html b/doc/dom/element/offset/new/index.html new file mode 100644 index 000000000..e936123f5 --- /dev/null +++ b/doc/dom/element/offset/new/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | new Element.Offset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Element.Offset +

    + + + + +
    +
    +
    +
    +
    +
    new(left, top)
    + + +

    Instantiates an Element.Offset. You shouldn't need to call this +directly.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/offset/prototype/inspect/index.html b/doc/dom/element/offset/prototype/inspect/index.html new file mode 100644 index 000000000..462ae7d76 --- /dev/null +++ b/doc/dom/element/offset/prototype/inspect/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Offset#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Element.Offset#inspect() → String
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/offset/prototype/relativeto/index.html b/doc/dom/element/offset/prototype/relativeto/index.html new file mode 100644 index 000000000..0b4b1b537 --- /dev/null +++ b/doc/dom/element/offset/prototype/relativeto/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset#relativeTo + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Offset#relativeTo +

    + + + + +
    +
    +
    +
    +
    +
    Element.Offset#relativeTo(offset) → Element.Offset
    +
      +
    • + offset + (Element.Offset) + – Another offset to compare to. +
    • +
    + + +

    Returns a new Element.Offset with its origin at the given +offset. Useful for determining an element's distance from another +arbitrary element.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/offset/prototype/toarray/index.html b/doc/dom/element/offset/prototype/toarray/index.html new file mode 100644 index 000000000..55078ba87 --- /dev/null +++ b/doc/dom/element/offset/prototype/toarray/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Offset#toArray +

    + + + + +
    +
    +
    +
    +
    +
    Element.Offset#toArray() → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/offset/prototype/tostring/index.html b/doc/dom/element/offset/prototype/tostring/index.html new file mode 100644 index 000000000..d96ebfd69 --- /dev/null +++ b/doc/dom/element/offset/prototype/tostring/index.html @@ -0,0 +1,145 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.Offset#toString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element.Offset#toString +

    + + + + +
    +
    +
    +
    +
    +
    Element.Offset#toString() → String
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/on/index.html b/doc/dom/element/on/index.html new file mode 100644 index 000000000..99d2ea8b0 --- /dev/null +++ b/doc/dom/element/on/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.on + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.on +

    + + + + +
    +
    +
    +
    +
    +
    Element.on(element, eventName[, selector], callback) → Element
    + + +

    See Event.on.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/positionedoffset/index.html b/doc/dom/element/positionedoffset/index.html new file mode 100644 index 000000000..ee2357e60 --- /dev/null +++ b/doc/dom/element/positionedoffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.positionedOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.positionedOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element.positionedOffset(element) → Element.Offset
    + + +

    Returns element's offset relative to its closest positioned ancestor +(the element that would be returned by Element.getOffsetParent).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/previous/index.html b/doc/dom/element/previous/index.html new file mode 100644 index 000000000..5dbff5736 --- /dev/null +++ b/doc/dom/element/previous/index.html @@ -0,0 +1,411 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.previous + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.previous +

    + + + + +
    +
    +
    +
    +
    +
    Element.previous(element[, expression[, index = 0]]) → Element
    Element.previous(element[, index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first previous sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all previous siblings are considered. If none matches these +criteria, undefined is returned.

    + +
    More information
    + +

    The Element.previous method is part of Prototype's ultimate DOM +traversal toolkit (check out Element.up, Element.down and +Element.next for some more Prototypish niceness). It allows precise +index-based and/or CSS expression-based selection of any of element's +previous siblings. (Note that two elements are considered siblings if +they have the same parent, so for example, the head and body elements +are siblings—their parent is the html element.)

    + +

    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 (see +Element.extend) allowing chaining:

    + +
    $(element).down('p').previous('ul', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's previous sibling is returned +(this is similar as calling previousSibling except Element.previous +returns an already extended element).

    + +

    If index is defined, element's corresponding previous sibling is +returned. (This is equivalent to selecting an element from the array of +elements returned by the method Element.previousSiblings). Note that +the sibling right above element has an index of 0.

    + +

    If expression is defined, Element.previous will return the element +first previous sibling that matches it.

    + +

    If both expression and index are defined, Element.previous will +collect all of element's previous siblings matching the given CSS +expression and will return the one at the specified index.

    + +

    In all of the above cases, if no previous sibling is found, +undefined will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3>Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious" class="yummy">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first previous sibling of "#saying":

    + +
    $('saying').previous();
    +// or:
    +$('saying').previous(0);
    +// -> ul#list-of-apples
    +
    +
    + +

    Get the second previous sibling of "#saying":

    + +
    $('saying').previous(1);
    +// -> h3
    +
    +
    + +

    Get the first previous sibling of "#saying" with node name "h3":

    + +
    $('saying').previous('h3');
    +// -> h3
    +
    +
    + +

    Get the first previous sibling of "#ida-red" with class name "yummy":

    + +
    $('ida-red').previous('.yummy');
    +// -> li#mutsu
    +
    +
    + +

    Get the second previous sibling of "#ida-red" with class name "yummy":

    + +
    $('ida-red').previous('.yummy', 1);
    +// -> li#golden-delicious
    +
    +
    + +

    Try to get the sixth previous sibling of "#ida-red":

    + +
    $('ida-red').previous(5);
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/previoussiblings/index.html b/doc/dom/element/previoussiblings/index.html new file mode 100644 index 000000000..4b13f1ef7 --- /dev/null +++ b/doc/dom/element/previoussiblings/index.html @@ -0,0 +1,330 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.previousSiblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.previousSiblings +

    + + + + +
    +
    +
    +
    +
    +
    Element.previousSiblings(element) → [Element…]
    + + +

    Collects all of element's previous siblings and returns them as an +Array of elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the <head> and <body> elements are siblings (their parent is the +<html> element). Previous-siblings are simply the ones which precede +element in the document.

    + +

    The returned Array reflects the siblings inversed order in the +document (e.g. an index of 0 refers to the lowest sibling i.e., the one +closest to element).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mcintosh').previousSiblings();
    +// -> [li#mutsu, li#golden-delicious]
    + $('golden-delicious').previousSiblings();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/absolutize/index.html b/doc/dom/element/prototype/absolutize/index.html new file mode 100644 index 000000000..7f06e39aa --- /dev/null +++ b/doc/dom/element/prototype/absolutize/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#absolutize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#absolutize +

    + + + + +
    +
    +
    +
    +
    +
    Element#absolutize() → Element
    + + +

    Turns element into an absolutely-positioned element without +changing its position in the page layout.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/addclassname/index.html b/doc/dom/element/prototype/addclassname/index.html new file mode 100644 index 000000000..f3a5d69da --- /dev/null +++ b/doc/dom/element/prototype/addclassname/index.html @@ -0,0 +1,322 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#addClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#addClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element#addClassName(className) → Element
    +
      +
    • + className + (String) + – The class name to add. +
    • +
    + + +

    Adds the given CSS class to element.

    + +
    Example
    + +

    Assuming this HTML:

    + +
    <div id="mutsu" class="apple fruit"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').className;
    +// -> 'apple fruit'
    +$('mutsu').addClassName('food');
    +$('mutsu').className;
    +// -> 'apple fruit food'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/adjacent/index.html b/doc/dom/element/prototype/adjacent/index.html new file mode 100644 index 000000000..b896f4e05 --- /dev/null +++ b/doc/dom/element/prototype/adjacent/index.html @@ -0,0 +1,331 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#adjacent + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#adjacent +

    + + + + +
    +
    +
    +
    +
    +
    Element#adjacent(selector...) → [Element…]
    +
      +
    • + selector + (String) + – A CSS selector. +
    • +
    + + +

    Finds all siblings of the current element that match the given +selector(s). If you provide multiple selectors, siblings matching any +of the selectors are included. If a sibling matches multiple selectors, +it is only included once. The order of the returned array is not defined.

    + +
    Example
    + +

    Assuming this list:

    + +
    <ul id="cities">
    +  <li class="us" id="nyc">New York</li>
    +  <li class="uk" id="lon">London</li>
    +  <li class="us" id="chi">Chicago</li>
    +  <li class="jp" id="tok">Tokyo</li>
    +  <li class="us" id="la">Los Angeles</li>
    +  <li class="us" id="aus">Austin</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('nyc').adjacent('li.us');
    +// -> [li#chi, li#la, li#aus]
    +$('nyc').adjacent('li.uk', 'li.jp');
    +// -> [li#lon, li#tok]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/ancestors/index.html b/doc/dom/element/prototype/ancestors/index.html new file mode 100644 index 000000000..5a6a0600e --- /dev/null +++ b/doc/dom/element/prototype/ancestors/index.html @@ -0,0 +1,327 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#ancestors + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#ancestors +

    + + + + +
    +
    +
    +
    +
    +
    Element#ancestors() → [Element…]
    + + +

    Collects all of element's ancestor elements and returns them as an +array of extended elements.

    + +

    The returned array's first element is element's direct ancestor (its +parentNode), the second one is its grandparent, and so on until the +<html> element is reached. <html> will always be the last member of +the array. Calling ancestors on the <html> element will return an +empty array.

    + +
    Example
    + +

    Assuming:

    + +
    <html>
    +[...]
    +  <body>
    +    <div id="father">
    +      <div id="kid">
    +      </div>
    +    </div>
    +  </body>
    +</html>
    +
    +
    + +

    Then:

    + +
    $('kid').ancestors();
    +// -> [div#father, body, html]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/childelements/index.html b/doc/dom/element/prototype/childelements/index.html new file mode 100644 index 000000000..cba70ad65 --- /dev/null +++ b/doc/dom/element/prototype/childelements/index.html @@ -0,0 +1,328 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#childElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#childElements +

    + + + + +
    +
    +
    +
    +
    +
    Element#childElements() → [Element…]
    + + +

    Collects all of the element's children and returns them as an array of +Element.extended elements, in document order. The first +entry in the array is the topmost child of element, the next is the +child after that, etc.

    + +

    Like all of Prototype's DOM traversal methods, Element.childElements +ignores text nodes and returns element nodes only.

    + +
    Example
    + +

    Assuming:

    + +
    <div id="australopithecus">
    +  Some text in a text node
    +  <div id="homo-erectus">
    +    <div id="homo-neanderthalensis"></div>
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('australopithecus').childElements();
    +// -> [div#homo-erectus]
    + $('homo-erectus').childElements();
    +// -> [div#homo-neanderthalensis, div#homo-sapiens]
    + $('homo-sapiens').childElements();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/classnames/index.html b/doc/dom/element/prototype/classnames/index.html new file mode 100644 index 000000000..6e7924849 --- /dev/null +++ b/doc/dom/element/prototype/classnames/index.html @@ -0,0 +1,303 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#classNames + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Element#classNames +

    + + + + +
    +
    +
    +
    +
    +
    Element#classNames() → [String…]
    + + +

    Returns a new instance of Element.ClassNames, an Enumerable +object used to read and write CSS class names of element.

    + +

    Deprecated, please see Element.addClassName, +Element.removeClassName, and Element.hasClassName. If you want +an array of classnames, you can use $w(element.className).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/cleanwhitespace/index.html b/doc/dom/element/prototype/cleanwhitespace/index.html new file mode 100644 index 000000000..df49a8cf1 --- /dev/null +++ b/doc/dom/element/prototype/cleanwhitespace/index.html @@ -0,0 +1,339 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#cleanWhitespace + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#cleanWhitespace +

    + + + + +
    +
    +
    +
    +
    +
    Element#cleanWhitespace() → Element
    + + +

    Removes all of element's child text nodes that contain only +whitespace. Returns element.

    + +

    This can be very useful when using standard properties like nextSibling, +previousSibling, firstChild or lastChild to walk the DOM. Usually +you'd only do that if you are interested in all of the DOM nodes, not +just Elements (since if you just need to traverse the Elements in the +DOM tree, you can use Element.up, Element.down, +Element.next, and Element.previous instead).

    + +

    Example

    + +

    Consider the following HTML snippet:

    + +
    <ul id="apples">
    +  <li>Mutsu</li>
    +  <li>McIntosh</li>
    +  <li>Ida Red</li>
    +</ul>
    +
    +
    + +

    Let's grab what we think is the first list item using the raw DOM +method:

    + +
    var element = $('apples');
    +element.firstChild.innerHTML;
    +// -> undefined
    +
    +
    + +

    It's undefined because the firstChild of the apples element is a +text node containing the whitespace after the end of the ul and before +the first li.

    + +

    If we remove the useless whitespace, then firstChild works as expected:

    + +
    var element = $('apples');
    +element.cleanWhitespace();
    +element.firstChild.innerHTML;
    +// -> 'Mutsu'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/clone/index.html b/doc/dom/element/prototype/clone/index.html new file mode 100644 index 000000000..3e45dfd17 --- /dev/null +++ b/doc/dom/element/prototype/clone/index.html @@ -0,0 +1,307 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#clone +

    + + + + +
    +
    +
    +
    +
    +
    Element#clone(deep) → Element
    +
      +
    • + deep + (Boolean) + – Whether to clone element's descendants as well. +
    • +
    + + +

    Returns a duplicate of element.

    + +

    A wrapper around DOM Level 2 Node#cloneNode, Element.clone cleans up +any expando properties defined by Prototype.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/cloneposition/index.html b/doc/dom/element/prototype/cloneposition/index.html new file mode 100644 index 000000000..0e37d62eb --- /dev/null +++ b/doc/dom/element/prototype/cloneposition/index.html @@ -0,0 +1,359 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#clonePosition + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#clonePosition +

    + + + + +
    +
    +
    +
    +
    +
    Element#clonePosition(source[, options]) → Element
    +
      +
    • + source + (Element | String) + – The source element (or its ID). +
    • +
    • + options + (Object) + – The position fields to clone. +
    • +
    + + +

    Clones the position and/or dimensions of source onto the element as +defined by options, with an optional offset for the left and top +properties.

    + +

    Note that the element will be positioned exactly like source whether or +not it is part of the same CSS containing +block.

    + +
    Options
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    NameDefaultDescription
    setLefttrueClones source's left CSS property onto element.
    setToptrueClones source's top CSS property onto element.
    setWidthtrueClones source's width onto element.
    setHeighttrueClones source's width onto element.
    offsetLeft0Number by which to offset element's left CSS property.
    offsetTop0Number by which to offset element's top CSS property.
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/cumulativeoffset/index.html b/doc/dom/element/prototype/cumulativeoffset/index.html new file mode 100644 index 000000000..fc1e60102 --- /dev/null +++ b/doc/dom/element/prototype/cumulativeoffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#cumulativeOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#cumulativeOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element#cumulativeOffset() → Element.Offset
    + + +

    Returns the offsets of element from the top left corner of the +document.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/cumulativescrolloffset/index.html b/doc/dom/element/prototype/cumulativescrolloffset/index.html new file mode 100644 index 000000000..86d17b604 --- /dev/null +++ b/doc/dom/element/prototype/cumulativescrolloffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#cumulativeScrollOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#cumulativeScrollOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element#cumulativeScrollOffset() → Element.Offset
    + + +

    Calculates the cumulative scroll offset of an element in nested +scrolling containers.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/descendantof/index.html b/doc/dom/element/prototype/descendantof/index.html new file mode 100644 index 000000000..617462b83 --- /dev/null +++ b/doc/dom/element/prototype/descendantof/index.html @@ -0,0 +1,325 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#descendantOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#descendantOf +

    + + + + +
    +
    +
    +
    +
    +
    Element#descendantOf(ancestor) → Boolean
    +
      +
    • + ancestor + (Element | String) + – The element to check against (or its ID). +
    • +
    + + +

    Checks if element is a descendant of ancestor.

    + +
    Example
    + +

    Assuming:

    + +
    <div id="australopithecus">
    +  <div id="homo-erectus">
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('homo-sapiens').descendantOf('australopithecus');
    +// -> true
    + $('homo-erectus').descendantOf('homo-sapiens');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/descendants/index.html b/doc/dom/element/prototype/descendants/index.html new file mode 100644 index 000000000..f32972ae6 --- /dev/null +++ b/doc/dom/element/prototype/descendants/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#descendants + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#descendants +

    + + + + +
    +
    +
    +
    +
    +
    Element#descendants() → [Element…]
    + + +

    Collects all of the element's descendants (its children, their children, +etc.) and returns them as an array of extended elements. As with all of +Prototype's DOM traversal methods, only Elements are returned, other +nodes (text nodes, etc.) are skipped.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/down/index.html b/doc/dom/element/prototype/down/index.html new file mode 100644 index 000000000..8696d72da --- /dev/null +++ b/doc/dom/element/prototype/down/index.html @@ -0,0 +1,409 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#down + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#down +

    + + + + +
    +
    +
    +
    +
    +
    Element#down([expression[, index = 0]]) → Element
    Element#down([index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first descendant (or the Nth descendant, if index +is specified) that matches expression. If no expression is +provided, all descendants are considered. If no descendant matches these +criteria, undefined is returned.

    + +
    More information
    + +

    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 +(see Element.extend) allowing chaining:

    + +
    $(element).down(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's first descendant is returned (this +is similar to calling firstChild except Element.down returns an +extended element.

    + +

    If index is defined, element's corresponding descendant is returned. +(This is equivalent to selecting an element from the array of elements +returned by the method Element.descendants.) Note that the first +element has an index of 0.

    + +

    If expression is defined, Element.down will return the first +descendant that matches it. This is a great way to grab the first item in +a list for example (just pass in 'li' as the method's first argument).

    + +

    If both expression and index are defined, Element.down will collect +all the descendants matching the given CSS expression and will return the +one at the specified index.

    + +

    In all of the above cases, if no descendant is found, undefined +will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <ul>
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first descendant of "#fruites":

    + +
    $('fruits').down();
    +// or:
    +$('fruits').down(0);
    +// -> li#apples
    +
    +
    + +

    Get the third descendant of "#fruits":

    + +
    $('fruits').down(3);
    +// -> li#golden-delicious
    +
    +
    + +

    Get the first descendant of "#apples" with the node name "li":

    + +
    $('apples').down('li');
    +// -> li#golden-delicious
    +
    +
    + +

    Get the first descendant of "#apples" with the node name "li" and the +class name "yummy":

    + +
    $('apples').down('li.yummy');
    +// -> li#mutsu
    +
    +
    + +

    Get the second descendant of "#fruits" with the class name "yummy":

    + +
    $('fruits').down('.yummy', 1);
    +// -> li#mcintosh
    +
    +
    + +

    Try to get the ninety-ninth descendant of "#fruits":

    + +
    $('fruits').down(99);
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/empty/index.html b/doc/dom/element/prototype/empty/index.html new file mode 100644 index 000000000..e152b9151 --- /dev/null +++ b/doc/dom/element/prototype/empty/index.html @@ -0,0 +1,308 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#empty + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#empty +

    + + + + +
    +
    +
    +
    +
    +
    Element#empty() → Element
    + + +

    Tests whether element is empty (i.e., contains only whitespace).

    + +
    Examples
    + +
    <div id="wallet">     </div>
    +<div id="cart">full!</div>
    + $('wallet').empty();
    +// -> true
    + $('cart').empty();
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/fire/index.html b/doc/dom/element/prototype/fire/index.html new file mode 100644 index 000000000..fd04859cf --- /dev/null +++ b/doc/dom/element/prototype/fire/index.html @@ -0,0 +1,336 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#fire + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#fire +

    + + + + +
    +
    +
    +
    +
    +
    Element#fire(eventName[, memo[, bubble = true]]) → Event
    + + +

    See Event.fire.

    + +

    Fires a custom event with the current element as its target.

    + +

    Element.fire creates a custom event with the given name, then triggers +it on the given element. The custom event has all the same properties +and methods of native events. Like a native event, it will bubble up +through the DOM unless its propagation is explicitly stopped.

    + +

    The optional second argument will be assigned to the memo property of +the event object so that it can be read by event handlers.

    + +

    Custom events are dispatched synchronously: Element.fire waits until +the event finishes its life cycle, then returns the event itself.

    + +
    Note
    + +

    Element.fire does not support firing native events. All custom event +names must be namespaced (using a colon). This is to avoid custom +event names conflicting with non-standard native DOM events such as +mousewheel and DOMMouseScroll.

    + +
    Examples
    + +
    document.observe("widget:frobbed", function(event) {
    +  console.log("Element with ID (" + event.target.id +
    +   ") frobbed widget #" + event.memo.widgetNumber + ".");
    +});
    + var someNode = $('foo');
    +someNode.fire("widget:frobbed", { widgetNumber: 19 });
    + //-> "Element with ID (foo) frobbed widget #19."
    +
    +
    + +
    Tip
    + +

    Events that have been stopped with Event.stop will have a boolean +stopped property set to true. Since Element.fire returns the custom +event, you can inspect this property to determine whether the event was +stopped.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/firstdescendant/index.html b/doc/dom/element/prototype/firstdescendant/index.html new file mode 100644 index 000000000..49b85c761 --- /dev/null +++ b/doc/dom/element/prototype/firstdescendant/index.html @@ -0,0 +1,324 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#firstDescendant + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#firstDescendant +

    + + + + +
    +
    +
    +
    +
    +
    Element#firstDescendant() → Element
    + + +

    Returns the first child that is an element.

    + +

    This is opposed to the firstChild DOM property, which will return +any node, including text nodes and comment nodes.

    + +
    Examples
    + +
    <div id="australopithecus">
    +  <div id="homo-erectus"><!-- Latin is super -->
    +    <div id="homo-neanderthalensis"></div>
    +    <div id="homo-sapiens"></div>
    +  </div>
    +</div>
    +
    +
    + +

    Then:

    + +
    $('australopithecus').firstDescendant();
    +// -> div#homo-herectus
    + // the DOM property returns any first node
    +$('homo-herectus').firstChild;
    +// -> comment node "Latin is super"
    + // this is what we want!
    +$('homo-herectus').firstDescendant();
    +// -> div#homo-neanderthalensis
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getdimensions/index.html b/doc/dom/element/prototype/getdimensions/index.html new file mode 100644 index 000000000..506c64467 --- /dev/null +++ b/doc/dom/element/prototype/getdimensions/index.html @@ -0,0 +1,326 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getDimensions + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getDimensions +

    + + + + +
    +
    +
    +
    +
    +
    Element#getDimensions() → Object
    + + +

    Finds the computed width and height of element and returns them as +key/value pairs of an object.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    In order to avoid calling the method twice, you should consider caching +the values returned in a variable as shown below. If you only need +element's width or height, consider using Element.getWidth or +Element.getHeight instead.

    + +

    Note that all values are returned as numbers only although they are +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    var dimensions = $('rectangle').getDimensions();
    +// -> {width: 200, height: 100}
    + dimensions.width;
    +// -> 200
    + dimensions.height;
    +// -> 100
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getelementsbyselector/index.html b/doc/dom/element/prototype/getelementsbyselector/index.html new file mode 100644 index 000000000..01df2bd7e --- /dev/null +++ b/doc/dom/element/prototype/getelementsbyselector/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getElementsBySelector + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getElementsBySelector +

    + + + + +
    +
    +
    +
    +
    +
    Element#getElementsBySelector(selector) → [Element…]
    + + + + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getheight/index.html b/doc/dom/element/prototype/getheight/index.html new file mode 100644 index 000000000..b55014197 --- /dev/null +++ b/doc/dom/element/prototype/getheight/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getHeight + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getHeight +

    + + + + +
    +
    +
    +
    +
    +
    Element#getHeight() → Number
    + + +

    Returns the height of element.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    For performance reasons, if you need to query both width and height of +element, you should consider using Element.getDimensions instead.

    + +

    Note that the value returned is a number only although it is +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    $('rectangle').getHeight();
    +// -> 100
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getlayout/index.html b/doc/dom/element/prototype/getlayout/index.html new file mode 100644 index 000000000..a925d7550 --- /dev/null +++ b/doc/dom/element/prototype/getlayout/index.html @@ -0,0 +1,305 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getLayout + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getLayout +

    + + + + +
    +
    +
    +
    +
    +
    Element#getLayout(preCompute) → Element.Layout
    + + +

    Returns an instance of Element.Layout for measuring an element's +dimensions.

    + +

    Note that this method returns a new Element.Layout object each time +it's called. If you want to take advantage of measurement caching, +retain a reference to one Element.Layout object, rather than calling +Element.getLayout whenever you need a measurement. You should call +Element.getLayout again only when the values in an existing +Element.Layout object have become outdated.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getoffsetparent/index.html b/doc/dom/element/prototype/getoffsetparent/index.html new file mode 100644 index 000000000..d0740fd61 --- /dev/null +++ b/doc/dom/element/prototype/getoffsetparent/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getOffsetParent + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getOffsetParent +

    + + + + +
    +
    +
    +
    +
    +
    Element#getOffsetParent() → Element
    + + +

    Returns element's closest positioned ancestor. If none is found, the +body element is returned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getopacity/index.html b/doc/dom/element/prototype/getopacity/index.html new file mode 100644 index 000000000..4b68e8692 --- /dev/null +++ b/doc/dom/element/prototype/getopacity/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getOpacity + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getOpacity +

    + + + + +
    +
    +
    +
    +
    +
    Element#getOpacity() → String | null
    + + +

    Returns the opacity of the element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getstorage/index.html b/doc/dom/element/prototype/getstorage/index.html new file mode 100644 index 000000000..7afdf0d38 --- /dev/null +++ b/doc/dom/element/prototype/getstorage/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getStorage + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getStorage +

    + + + + +
    +
    +
    +
    +
    +
    Element#getStorage() → Hash
    + + +

    Returns the Hash object that stores custom metadata for this element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getstyle/index.html b/doc/dom/element/prototype/getstyle/index.html new file mode 100644 index 000000000..27649f899 --- /dev/null +++ b/doc/dom/element/prototype/getstyle/index.html @@ -0,0 +1,354 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getStyle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getStyle +

    + + + + +
    +
    +
    +
    +
    +
    Element#getStyle(style) → String | null
    +
      +
    • + style + (String) + – The property name to be retrieved. +
    • +
    + + +

    Returns the given CSS property value of element. The property can be +specified in either its CSS form (font-size) or its camelized form +(fontSize).

    + +

    This method looks up the CSS property of an element whether it was +applied inline or in a stylesheet. It works around browser inconsistencies +regarding float, opacity, which returns a value between 0 +(fully transparent) and 1 (fully opaque), position properties +(left, top, right and bottom) and when getting the dimensions +(width or height) of hidden elements.

    + +
    Examples
    + +
    $(element).getStyle('font-size');
    +// equivalent:
    + $(element).getStyle('fontSize');
    +// -> '12px'
    +
    +
    + +
    Notes
    + +

    Internet Explorer returns literal values while other browsers return +computed values.

    + +

    Consider the following HTML snippet:

    + +
    <style>
    +  #test {
    +    font-size: 12px;
    +    margin-left: 1em;
    +  }
    +</style>
    +<div id="test"></div>
    +
    +
    + +

    Then:

    + +
    $('test').getStyle('margin-left');
    +// -> '1em' in Internet Explorer,
    +// -> '12px' elsewhere.
    +
    +
    + +

    Safari returns null for any non-inline property if the element is +hidden (has display set to 'none').

    + +

    Not all CSS shorthand properties are supported. You may only use the CSS +properties described in the +Document Object Model (DOM) Level 2 Style Specification.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/getwidth/index.html b/doc/dom/element/prototype/getwidth/index.html new file mode 100644 index 000000000..379ccddfb --- /dev/null +++ b/doc/dom/element/prototype/getwidth/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#getWidth + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#getWidth +

    + + + + +
    +
    +
    +
    +
    +
    Element#getWidth() → Number
    + + +

    Returns the width of element.

    + +

    This method returns correct values on elements whose display is set to +none either in an inline style rule or in an CSS stylesheet.

    + +

    For performance reasons, if you need to query both width and height of +element, you should consider using Element.getDimensions instead.

    + +

    Note that the value returned is a number only although it is +expressed in pixels.

    + +
    Examples
    + +
    <div id="rectangle" style="font-size: 10px; width: 20em; height: 10em"></div>
    +
    +
    + +

    Then:

    + +
    $('rectangle').getWidth();
    +// -> 200
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/hasattribute/index.html b/doc/dom/element/prototype/hasattribute/index.html new file mode 100644 index 000000000..4089bd83d --- /dev/null +++ b/doc/dom/element/prototype/hasattribute/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#hasAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#hasAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element#hasAttribute(attribute) → Boolean
    + + +

    Simulates the standard compliant DOM method +hasAttribute +for browsers missing it (Internet Explorer 6 and 7).

    + +
    Example
    + +
    <a id="link" href="http://prototypejs.org">Prototype</a>
    +
    +
    + +

    Then:

    + +
    $('link').hasAttribute('href');
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/hasclassname/index.html b/doc/dom/element/prototype/hasclassname/index.html new file mode 100644 index 000000000..75cb6ee1e --- /dev/null +++ b/doc/dom/element/prototype/hasclassname/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#hasClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#hasClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element#hasClassName(className) → Boolean
    + + +

    Checks for the presence of CSS class className on element.

    + +
    Examples
    + +
    <div id="mutsu" class="apple fruit food"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').hasClassName('fruit');
    +// -> true
    + $('mutsu').hasClassName('vegetable');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/hide/index.html b/doc/dom/element/prototype/hide/index.html new file mode 100644 index 000000000..49edaf9db --- /dev/null +++ b/doc/dom/element/prototype/hide/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#hide + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#hide +

    + + + + +
    +
    +
    +
    +
    +
    Element#hide() → Element
    + + +

    Sets display: none on element. Returns element.

    + +
    Examples
    + +

    Hide a single element:

    + +
    <div id="error-message"></div>
    + $('error-message').hide();
    +// -> Element (and hides div#error-message)
    +
    +
    + +

    Hide multiple elements using Enumerable#each:

    + +
    ['content', 'navigation', 'footer'].each(Element.hide);
    +// -> ['content', 'navigation', 'footer']
    +
    +
    + +

    Hide multiple elements using Enumerable#invoke:

    + +
    $('content', 'navigation', 'footer').invoke('hide');
    +// -> [Element, Element, Element]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/identify/index.html b/doc/dom/element/prototype/identify/index.html new file mode 100644 index 000000000..50092c889 --- /dev/null +++ b/doc/dom/element/prototype/identify/index.html @@ -0,0 +1,327 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#identify + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#identify +

    + + + + +
    +
    +
    +
    +
    +
    Element#identify() → String
    + + +

    Returns element's ID. If element does not have an ID, one is +generated, assigned to element, and returned.

    + +
    Examples
    + +

    Original HTML:

    + +
      <ul>
    +    <li id="apple">apple</li>
    +    <li>orange</li>
    +  </ul>
    +
    +
    + +

    JavaScript:

    + +
      $('apple').identify();
    +  // -> 'apple'
    +   $('apple').next().identify();
    +  // -> 'anonymous_element_1'
    +
    +
    + +

    Resulting HTML:

    + +
      <ul>
    +    <li id="apple">apple</li>
    +    <li id="anonymous_element_1">orange</li>
    +  </ul>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/immediatedescendants/index.html b/doc/dom/element/prototype/immediatedescendants/index.html new file mode 100644 index 000000000..58cb82942 --- /dev/null +++ b/doc/dom/element/prototype/immediatedescendants/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#immediateDescendants + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Element#immediateDescendants +

    + + + + +
    +
    +
    +
    +
    +
    Element#immediateDescendants() → [Element…]
    + + +

    This method is deprecated, please see Element.childElements.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/insert/index.html b/doc/dom/element/prototype/insert/index.html new file mode 100644 index 000000000..7818aeef2 --- /dev/null +++ b/doc/dom/element/prototype/insert/index.html @@ -0,0 +1,352 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#insert + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#insert +

    + + + + +
    +
    +
    +
    +
    +
    Element#insert(content) → Element
    + + + +

    Inserts content above, below, at the top, and/or at the bottom of +the given element, depending on the option(s) given.

    + +

    insert accepts content in any of these forms:

    + +
      +
    • String: A string of HTML to be parsed and rendered
    • +
    • Element: An Element instance to insert
    • +
    • ...any object with a toElement method: The method is called and the resulting element used
    • +
    • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
    • +
    + +

    The content argument can be the content to insert, in which case the +implied insertion point is bottom, or an object that specifies one or +more insertion points (e.g., { bottom: "foo", top: "bar" }).

    + +

    Accepted insertion points are:

    + +
      +
    • before (as element's previous sibling)
    • +
    • after (as element's next sibling)
    • +
    • top (as element's first child)
    • +
    • bottom (as element's last child)
    • +
    + +

    Note that if the inserted HTML contains any <script> tag, these will be +automatically evaluated after the insertion (insert internally calls +String.evalScripts when inserting HTML).

    + +
    Examples
    + +

    Insert the given HTML at the bottom of the element (using the default):

    + +
    $('myelement').insert("<p>HTML to append</p>");
    + $('myelement').insert({
    +  top: new Element('img', {src: 'logo.png'})
    +});
    +
    +
    + +

    Put hrs before and after the element:

    + +
    $('myelement').insert({
    +  before: "<hr>",
    +  after: "<hr>"
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/inspect/index.html b/doc/dom/element/prototype/inspect/index.html new file mode 100644 index 000000000..9959c64fb --- /dev/null +++ b/doc/dom/element/prototype/inspect/index.html @@ -0,0 +1,319 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Element#inspect() → String
    + + +

    Returns the debug-oriented string representation of element.

    + +

    For more information on inspect methods, see Object.inspect.

    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu" class="yummy apple">Mutsu</li>
    +  <li id="mcintosh" class="yummy">McIntosh</li>
    +  <li></li>
    +</ul>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('golden-delicious').inspect();
    +// -> '<li id="golden-delicious">'
    + $('mutsu').inspect();
    +// -> '<li id="mutsu" class="yummy apple">'
    + $('mutsu').next().inspect();
    +// -> '<li>'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/makeclipping/index.html b/doc/dom/element/prototype/makeclipping/index.html new file mode 100644 index 000000000..6bd650673 --- /dev/null +++ b/doc/dom/element/prototype/makeclipping/index.html @@ -0,0 +1,344 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#makeClipping + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#makeClipping +

    + + + + +
    +
    +
    +
    +
    +
    Element#makeClipping() → Element
    + + +

    Simulates the poorly-supported CSS clip property by setting element's +overflow value to hidden.

    + +

    To undo clipping, use Element.undoClipping.

    + +

    The visible area is determined by element's width and height.

    + +
    Example
    + +
    <div id="framer">
    +  <img src="/assets/2007/1/14/chairs.jpg" alt="example" />
    +</div>
    +
    +
    + +

    Then:

    + +
    $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +// -> Element
    +
    +
    + +

    Another example:

    + +
    <a id="clipper" href="#">Click me to try it out.</a>
    + <div id="framer">
    +  <img src="/assets/2007/2/24/chairs.jpg" alt="example" />
    +</div>
    + <script type="text/javascript" charset="utf-8">
    +  var Example = {
    +    clip: function(){
    +      $('clipper').update('undo clipping!');
    +      $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +    },
    +    unClip: function(){
    +      $('clipper').update('clip!');
    +      $('framer').undoClipping();
    +    },
    +    toggleClip: function(event){
    +      if($('clipper').innerHTML == 'undo clipping!') Example.unClip();
    +      else Example.clip();
    +      Event.stop(event);
    +    }
    +  };
    +  Event.observe('clipper', 'click', Example.toggleClip);
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/makepositioned/index.html b/doc/dom/element/prototype/makepositioned/index.html new file mode 100644 index 000000000..3332848a6 --- /dev/null +++ b/doc/dom/element/prototype/makepositioned/index.html @@ -0,0 +1,302 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#makePositioned + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#makePositioned +

    + + + + +
    +
    +
    +
    +
    +
    Element#makePositioned() → Element
    + + +

    Allows for the easy creation of a CSS containing block by setting +element's CSS position to relative if its initial position is +either static or undefined.

    + +

    To revert back to element's original CSS position, use +Element.undoPositioned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/match/index.html b/doc/dom/element/prototype/match/index.html new file mode 100644 index 000000000..22622e9bb --- /dev/null +++ b/doc/dom/element/prototype/match/index.html @@ -0,0 +1,330 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#match +

    + + + + +
    +
    +
    +
    +
    +
    Element#match(selector) → boolean
    +
      +
    • + selector + (String) + – A CSS selector. +
    • +
    + + +

    Checks if element matches the given CSS selector.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <ul>
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +  </li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('fruits').match('ul');
    +// -> true
    + $('mcintosh').match('li#mcintosh.yummy');
    +// -> true
    + $('fruits').match('p');
    +// -> false
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/measure/index.html b/doc/dom/element/prototype/measure/index.html new file mode 100644 index 000000000..92ae56712 --- /dev/null +++ b/doc/dom/element/prototype/measure/index.html @@ -0,0 +1,303 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#measure + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#measure +

    + + + + +
    +
    +
    +
    +
    +
    Element#measure(property) → Number
    + + +

    Gives the pixel value of element's dimension specified by +property.

    + +

    Useful for one-off measurements of elements. If you find yourself +calling this method frequently over short spans of code, you might want +to call Element.getLayout and operate on the Element.Layout +object itself (thereby taking advantage of measurement caching).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/next/index.html b/doc/dom/element/prototype/next/index.html new file mode 100644 index 000000000..4be767278 --- /dev/null +++ b/doc/dom/element/prototype/next/index.html @@ -0,0 +1,411 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#next + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#next +

    + + + + +
    +
    +
    +
    +
    +
    Element#next([expression[, index = 0]]) → Element
    Element#next([index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first following sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all following siblings are considered. If none matches these +criteria, undefined is returned.

    + +
    More information
    + +

    The Element.next method is part of Prototype's ultimate DOM traversal +toolkit (check out Element.up, Element.down and +Element.previous for some more Prototypish niceness). It allows +precise index-based and/or CSS expression-based selection of any of +element's following siblings. (Note that two elements are considered +siblings if they have the same parent, so for example, the head and +body elements are siblings—their parent is the html element.)

    + +

    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 (see +Element.extend) allowing chaining:

    + +
    $(element).down(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's following sibling is returned +(this is similar as calling nextSibling except Element.next returns an +already extended element).

    + +

    If index is defined, element's corresponding following sibling is +returned. (This is equivalent to selecting an element from the array of +elements returned by the method Element.nextSiblings). Note that the +sibling right below element has an index of 0.

    + +

    If expression is defined, Element.next will return the element first +following sibling that matches it.

    + +

    If both expression and index are defined, Element.next will collect +all of element's following siblings matching the given CSS expression +and will return the one at the specified index.

    + +

    In all of the above cases, if no following sibling is found, +undefined will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3 id="title">Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious">Golden Delicious</li>
    +      <li id="mutsu">Mutsu</li>
    +      <li id="mcintosh" class="yummy">McIntosh</li>
    +      <li id="ida-red" class="yummy">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first sibling after "#title":

    + +
    $('title').next();
    +// or:
    +$('title').next(0);
    +// -> ul#list-of-apples
    +
    +
    + +

    Get the second sibling after "#title":

    + +
    $('title').next(1);
    +// -> p#saying
    +
    +
    + +

    Get the first sibling after "#title" with node name "p":

    + +
    $('title').next('p');
    +// -> p#sayings
    +
    +
    + +

    Get the first sibling after "#golden-delicious" with class name "yummy":

    + +
    $('golden-delicious').next('.yummy');
    +// -> li#mcintosh
    +
    +
    + +

    Get the second sibling after "#golden-delicious" with class name "yummy":

    + +
    $('golden-delicious').next('.yummy', 1);
    +// -> li#ida-red
    +
    +
    + +

    Try to get the first sibling after "#ida-red":

    + +
    $('ida-red').next();
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/nextsiblings/index.html b/doc/dom/element/prototype/nextsiblings/index.html new file mode 100644 index 000000000..e4306289f --- /dev/null +++ b/doc/dom/element/prototype/nextsiblings/index.html @@ -0,0 +1,329 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#nextSiblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#nextSiblings +

    + + + + +
    +
    +
    +
    +
    +
    Element#nextSiblings() → [Element…]
    + + +

    Collects all of element's next siblings and returns them as an Array +of elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the head and body elements are siblings (their parent is the html +element). Next-siblings are simply the ones which follow element in the +document.

    + +

    The returned Array reflects the siblings order in the document +(e.g. an index of 0 refers to the sibling right below element).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mutsu').nextSiblings();
    +// -> [li#mcintosh, li#ida-red]
    + $('ida-red').nextSiblings();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/observe/index.html b/doc/dom/element/prototype/observe/index.html new file mode 100644 index 000000000..9bafda775 --- /dev/null +++ b/doc/dom/element/prototype/observe/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#observe + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#observe +

    + + + + +
    +
    +
    +
    +
    +
    Element#observe(eventName, handler) → Element
    + + +

    See Event.observe.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/on/index.html b/doc/dom/element/prototype/on/index.html new file mode 100644 index 000000000..292714444 --- /dev/null +++ b/doc/dom/element/prototype/on/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#on + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#on +

    + + + + +
    +
    +
    +
    +
    +
    Element#on(eventName[, selector], callback) → Element
    + + +

    See Event.on.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/positionedoffset/index.html b/doc/dom/element/prototype/positionedoffset/index.html new file mode 100644 index 000000000..d88d0b543 --- /dev/null +++ b/doc/dom/element/prototype/positionedoffset/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#positionedOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#positionedOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element#positionedOffset() → Element.Offset
    + + +

    Returns element's offset relative to its closest positioned ancestor +(the element that would be returned by Element.getOffsetParent).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/previous/index.html b/doc/dom/element/prototype/previous/index.html new file mode 100644 index 000000000..b7024e3b0 --- /dev/null +++ b/doc/dom/element/prototype/previous/index.html @@ -0,0 +1,411 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#previous + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#previous +

    + + + + +
    +
    +
    +
    +
    +
    Element#previous([expression[, index = 0]]) → Element
    Element#previous([index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first previous sibling (or the Nth, if index +is specified) that matches expression. If no expression is +provided, all previous siblings are considered. If none matches these +criteria, undefined is returned.

    + +
    More information
    + +

    The Element.previous method is part of Prototype's ultimate DOM +traversal toolkit (check out Element.up, Element.down and +Element.next for some more Prototypish niceness). It allows precise +index-based and/or CSS expression-based selection of any of element's +previous siblings. (Note that two elements are considered siblings if +they have the same parent, so for example, the head and body elements +are siblings—their parent is the html element.)

    + +

    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 (see +Element.extend) allowing chaining:

    + +
    $(element).down('p').previous('ul', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's previous sibling is returned +(this is similar as calling previousSibling except Element.previous +returns an already extended element).

    + +

    If index is defined, element's corresponding previous sibling is +returned. (This is equivalent to selecting an element from the array of +elements returned by the method Element.previousSiblings). Note that +the sibling right above element has an index of 0.

    + +

    If expression is defined, Element.previous will return the element +first previous sibling that matches it.

    + +

    If both expression and index are defined, Element.previous will +collect all of element's previous siblings matching the given CSS +expression and will return the one at the specified index.

    + +

    In all of the above cases, if no previous sibling is found, +undefined will be returned.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3>Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious" class="yummy">Golden Delicious</li>
    +      <li id="mutsu" class="yummy">Mutsu</li>
    +      <li id="mcintosh">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Get the first previous sibling of "#saying":

    + +
    $('saying').previous();
    +// or:
    +$('saying').previous(0);
    +// -> ul#list-of-apples
    +
    +
    + +

    Get the second previous sibling of "#saying":

    + +
    $('saying').previous(1);
    +// -> h3
    +
    +
    + +

    Get the first previous sibling of "#saying" with node name "h3":

    + +
    $('saying').previous('h3');
    +// -> h3
    +
    +
    + +

    Get the first previous sibling of "#ida-red" with class name "yummy":

    + +
    $('ida-red').previous('.yummy');
    +// -> li#mutsu
    +
    +
    + +

    Get the second previous sibling of "#ida-red" with class name "yummy":

    + +
    $('ida-red').previous('.yummy', 1);
    +// -> li#golden-delicious
    +
    +
    + +

    Try to get the sixth previous sibling of "#ida-red":

    + +
    $('ida-red').previous(5);
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/previoussiblings/index.html b/doc/dom/element/prototype/previoussiblings/index.html new file mode 100644 index 000000000..c20b30547 --- /dev/null +++ b/doc/dom/element/prototype/previoussiblings/index.html @@ -0,0 +1,330 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#previousSiblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#previousSiblings +

    + + + + +
    +
    +
    +
    +
    +
    Element#previousSiblings() → [Element…]
    + + +

    Collects all of element's previous siblings and returns them as an +Array of elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the <head> and <body> elements are siblings (their parent is the +<html> element). Previous-siblings are simply the ones which precede +element in the document.

    + +

    The returned Array reflects the siblings inversed order in the +document (e.g. an index of 0 refers to the lowest sibling i.e., the one +closest to element).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mcintosh').previousSiblings();
    +// -> [li#mutsu, li#golden-delicious]
    + $('golden-delicious').previousSiblings();
    +// -> []
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/readattribute/index.html b/doc/dom/element/prototype/readattribute/index.html new file mode 100644 index 000000000..da1f4aca3 --- /dev/null +++ b/doc/dom/element/prototype/readattribute/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#readAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#readAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element#readAttribute(attributeName) → String | null
    + + +

    Returns the value of element's attribute or null if attribute has +not been specified.

    + +

    This method serves two purposes. First it acts as a simple wrapper around +getAttribute which isn't a "real" function in Safari and Internet +Explorer (it doesn't have .apply or .call for instance). Secondly, it +cleans up the horrible mess Internet Explorer makes when handling +attributes.

    + +
    Examples
    + +
    <a id="tag" href="/tags/prototype" rel="tag" title="view related bookmarks." my_widget="some info.">Prototype</a>
    +
    +
    + +

    Then:

    + +
    $('tag').readAttribute('href');
    +// -> '/tags/prototype'
    + $('tag').readAttribute('title');
    +// -> 'view related bookmarks.'
    + $('tag').readAttribute('my_widget');
    +// -> 'some info.'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/recursivelycollect/index.html b/doc/dom/element/prototype/recursivelycollect/index.html new file mode 100644 index 000000000..67af95eaf --- /dev/null +++ b/doc/dom/element/prototype/recursivelycollect/index.html @@ -0,0 +1,334 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#recursivelyCollect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#recursivelyCollect +

    + + + + +
    +
    +
    +
    +
    +
    Element#recursivelyCollect(property) → [Element…]
    + + +

    Recursively collects elements whose relationship to element is +specified by property. property has to be a property (a method +won't do!) of element that points to a single DOM node (e.g., +nextSibling or parentNode).

    + +
    More information
    + +

    This method is used internally by Element.ancestors, +Element.descendants, Element.nextSiblings, +Element.previousSiblings and Element.siblings which offer really +convenient way to grab elements, so directly accessing +Element.recursivelyCollect should seldom be needed. However, if you +are after something out of the ordinary, it is the way to go.

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <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>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('fruits').recursivelyCollect('firstChild');
    +// -> [li#apples, ul#list-of-apples, li#golden-delicious, p]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/relativize/index.html b/doc/dom/element/prototype/relativize/index.html new file mode 100644 index 000000000..c03ea59ed --- /dev/null +++ b/doc/dom/element/prototype/relativize/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#relativize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#relativize +

    + + + + +
    +
    +
    +
    +
    +
    Element#relativize() → Element
    + + +

    Turns element into a relatively-positioned element without changing +its position in the page layout.

    + +

    Used to undo a call to Element.absolutize.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/remove/index.html b/doc/dom/element/prototype/remove/index.html new file mode 100644 index 000000000..7c2149da6 --- /dev/null +++ b/doc/dom/element/prototype/remove/index.html @@ -0,0 +1,329 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#remove + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#remove +

    + + + + +
    +
    +
    +
    +
    +
    Element#remove() → Element
    + + +

    Completely removes element from the document and returns it.

    + +

    If you would rather just hide the element and keep it around for further +use, try Element.hide instead.

    + +
    Examples
    + +
    // Before:
    +<ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('mutsu').remove();
    +// -> Element (and removes li#mutsu)
    +
    +
    + +

    The resulting HTML:

    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/removeclassname/index.html b/doc/dom/element/prototype/removeclassname/index.html new file mode 100644 index 000000000..3cf4bc1de --- /dev/null +++ b/doc/dom/element/prototype/removeclassname/index.html @@ -0,0 +1,314 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#removeClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#removeClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element#removeClassName(className) → Element
    + + +

    Removes CSS class className from element.

    + +
    Examples
    + +

    Assuming this HTML:

    + +
    <div id="mutsu" class="apple fruit food"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').removeClassName('food');
    +// -> Element
    + $('mutsu').classNames;
    +// -> 'apple fruit'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/replace/index.html b/doc/dom/element/prototype/replace/index.html new file mode 100644 index 000000000..6f7a2fa15 --- /dev/null +++ b/doc/dom/element/prototype/replace/index.html @@ -0,0 +1,366 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#replace + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#replace +

    + + + + +
    +
    +
    +
    +
    +
    Element#replace([newContent]) → Element
    + + +

    Replaces element itself with newContent and returns element.

    + +

    Keep in mind that this method returns the element that has just been +removed — not the element that took its place.

    + +

    newContent can be either plain text, an HTML snippet or any JavaScript +object which has a toString() method.

    + +

    If newContent contains any <script> tags, these will be evaluated +after element has been replaced (Element.replace internally calls +String#evalScripts).

    + +

    Note that if no argument is provided, Element.replace will simply +clear element of its content. However, using Element.remove to do so +is both faster and more standard compliant.

    + +
    Examples
    + +
    <div id="food">
    +  <div id="fruits">
    +    <p id="first">Kiwi, banana <em>and</em> apple.</p>
    +  </div>
    +</div>
    +
    +
    + +

    Passing an HTML snippet:

    + +
    $('first').replace('<ul id="favorite"><li>kiwi</li><li>banana</li><li>apple</li></ul>');
    +// -> Element (p#first)
    + $('fruits').innerHTML;
    +// -> '<ul id="favorite"><li>kiwi</li><li>banana</li><li>apple</li></ul>'
    +
    +
    + +

    Again, with a <script> tag thrown in:

    + +
    $('favorite').replace('<p id="still-first">Melon, oranges <em>and</em> grapes.</p><script>alert("removed!")</script>');
    +// -> Element (ul#favorite) and prints "removed!" in an alert dialog.
    + $('fruits').innerHTML;
    +// -> '<p id="still-first">Melon, oranges <em>and</em> grapes.</p>'
    +
    +
    + +

    With plain text:

    + +
    $('still-first').replace('Melon, oranges and grapes.');
    +// -> Element (p#still-first)
    + $('fruits').innerHTML;
    +// -> 'Melon, oranges and grapes.'
    +
    +
    + +

    Finally, relying on the toString() method:

    + +
    $('fruits').replace(123);
    +// -> Element
    + $('food').innerHTML;
    +// -> '123'
    +
    +
    + +
    Warning
    + +

    Using Element.replace as an instance method (e.g., +$('foo').replace('<p>Bar</p>')) causes errors in Opera 9 when used on +input elements. The replace property is reserved on input elements +as part of Web Forms 2. +As a workaround, use the generic version instead +(Element.replace('foo', '<p>Bar</p>')).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/retrieve/index.html b/doc/dom/element/prototype/retrieve/index.html new file mode 100644 index 000000000..632ee5084 --- /dev/null +++ b/doc/dom/element/prototype/retrieve/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#retrieve + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#retrieve +

    + + + + +
    +
    +
    +
    +
    +
    Element#retrieve(key[, defaultValue]) → ?
    + + +

    Retrieves custom metadata set on element with Element.store.

    + +

    If the value is undefined and defaultValue is given, it will be +stored on the element as its new value for that key, then returned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/scrollto/index.html b/doc/dom/element/prototype/scrollto/index.html new file mode 100644 index 000000000..ebcb36764 --- /dev/null +++ b/doc/dom/element/prototype/scrollto/index.html @@ -0,0 +1,308 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#scrollTo + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#scrollTo +

    + + + + +
    +
    +
    +
    +
    +
    Element#scrollTo() → Element
    + + +

    Scrolls the window so that element appears at the top of the viewport.

    + +

    This has a similar effect than what would be achieved using +HTML anchors +(except the browser's history is not modified).

    + +
    Example
    + +
    $(element).scrollTo();
    +// -> Element
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/select/index.html b/doc/dom/element/prototype/select/index.html new file mode 100644 index 000000000..104d92016 --- /dev/null +++ b/doc/dom/element/prototype/select/index.html @@ -0,0 +1,356 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#select +

    + + + + +
    +
    +
    +
    +
    +
    Element#select(expression...) → [Element…]
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Takes an arbitrary number of CSS selectors and returns an array of +descendants of element that match any of them.

    + +

    This method is very similar to $$ but can be used within the context +of one element, rather than the whole document. The supported CSS syntax +is identical, so please refer to the $$ docs for details.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3 title="yummy!">Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious" title="yummy!" >Golden Delicious</li>
    +      <li id="mutsu" title="yummy!">Mutsu</li>
    +      <li id="mcintosh">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('apples').select('[title="yummy!"]');
    +// -> [h3, li#golden-delicious, li#mutsu]
    + $('apples').select( 'p#saying', 'li[title="yummy!"]');
    +// -> [li#golden-delicious, li#mutsu,  p#saying]
    + $('apples').select('[title="disgusting!"]');
    +// -> []
    +
    +
    + +
    Tip
    + +

    Element.select can be used as a pleasant alternative to the native +method getElementsByTagName:

    + +
    var nodes  = $A(someUL.getElementsByTagName('li')).map(Element.extend);
    +var nodes2 = someUL.select('li');
    +
    +
    + +

    In the first example, you must explicitly convert the result set to an +Array (so that Prototype's Enumerable methods can be used) and +must manually call Element.extend on each node (so that custom +instance methods can be used on the nodes). Element.select takes care +of both concerns on its own.

    + +

    If you're using 1.6 or above (and the performance optimizations therein), +the speed difference between these two examples is negligible.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/setopacity/index.html b/doc/dom/element/prototype/setopacity/index.html new file mode 100644 index 000000000..9f8aeae0d --- /dev/null +++ b/doc/dom/element/prototype/setopacity/index.html @@ -0,0 +1,313 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#setOpacity + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#setOpacity +

    + + + + +
    +
    +
    +
    +
    +
    Element#setOpacity(opacity) → [Element…]
    + + +

    Sets the visual opacity of an element while working around inconsistencies +in various browsers. The opacity argument should be a floating point +number, where the value of 0 is fully transparent and 1 is fully opaque.

    + +

    Element.setStyle method uses Element.setOpacity internally when needed.

    + +
    Examples
    + +
    var element = $('myelement');
    +// set to 50% transparency
    +element.setOpacity(0.5);
    + // these are equivalent, but allow for setting more than
    +// one CSS property at once:
    +element.setStyle({ opacity: 0.5 });
    +element.setStyle("opacity: 0.5");
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/setstyle/index.html b/doc/dom/element/prototype/setstyle/index.html new file mode 100644 index 000000000..d2d4d7065 --- /dev/null +++ b/doc/dom/element/prototype/setstyle/index.html @@ -0,0 +1,334 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#setStyle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#setStyle +

    + + + + +
    +
    +
    +
    +
    +
    Element#setStyle(styles) → Element
    + + +

    Modifies element's CSS style properties. Styles are passed as a hash of +property-value pairs in which the properties are specified in their +camelized form.

    + +
    Examples
    + +
    $(element).setStyle({
    +  backgroundColor: '#900',
    +  fontSize: '12px'
    +});
    +// -> Element
    +
    +
    + +
    Notes
    + +

    The method transparently deals with browser inconsistencies for float +(however, as float is a reserved keyword, you must either escape it or +use cssFloat instead) and opacity (which accepts values between 0 +-fully transparent- and 1 -fully opaque-). You can safely use either of +the following across all browsers:

    + +
    $(element).setStyle({
    +  cssFloat: 'left',
    +  opacity: 0.5
    +});
    +// -> Element
    + $(element).setStyle({
    +  'float': 'left', // notice how float is surrounded by single quotes
    +  opacity: 0.5
    +});
    +// -> Element
    +
    +
    + +

    Not all CSS shorthand properties are supported. You may only use the CSS +properties described in the +Document Object Model (DOM) Level 2 Style Specification.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/show/index.html b/doc/dom/element/prototype/show/index.html new file mode 100644 index 000000000..465dd24fe --- /dev/null +++ b/doc/dom/element/prototype/show/index.html @@ -0,0 +1,339 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#show + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#show +

    + + + + +
    +
    +
    +
    +
    +
    Element#show() → Element
    + + +

    Removes display: none on element. Returns element.

    + +
    Examples
    + +

    Show a single element:

    + +
    <div id="error-message" style="display:none;"></div>
    + $('error-message').show();
    +// -> Element (and displays div#error-message)
    +
    +
    + +

    Show multiple elements using Enumerable#each:

    + +
    ['content', 'navigation', 'footer'].each(Element.show);
    +// -> ['content', 'navigation', 'footer']
    +
    +
    + +

    Show multiple elements using Enumerable#invoke:

    + +
    $('content', 'navigation', 'footer').invoke('show');
    +// -> [Element, Element, Element]
    +
    +
    + +
    Notes
    + +

    Element.show cannot display elements hidden via CSS stylesheets. +Note that this is not a Prototype limitation but a consequence of how the +CSS display property works.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    + $('hidden-by-css').show(); // DOES NOT WORK!
    +// -> Element (div#error-message is still hidden!)
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/siblings/index.html b/doc/dom/element/prototype/siblings/index.html new file mode 100644 index 000000000..e8df983de --- /dev/null +++ b/doc/dom/element/prototype/siblings/index.html @@ -0,0 +1,326 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#siblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#siblings +

    + + + + +
    +
    +
    +
    +
    +
    Element#siblings() → [Element…]
    + + +

    Collects all of element's siblings and returns them as an Array of +elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the head and body elements are siblings (their parent is the html +element).

    + +

    The returned Array reflects the siblings' order in the document (e.g. +an index of 0 refers to element's topmost sibling).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mutsu').siblings();
    +// -> [li#golden-delicious, li#mcintosh, li#ida-red]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/stopobserving/index.html b/doc/dom/element/prototype/stopobserving/index.html new file mode 100644 index 000000000..062648b0a --- /dev/null +++ b/doc/dom/element/prototype/stopobserving/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#stopObserving + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#stopObserving +

    + + + + +
    +
    +
    +
    +
    +
    Element#stopObserving([eventName[, handler]]) → Element
    + + +

    See Event.stopObserving.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/store/index.html b/doc/dom/element/prototype/store/index.html new file mode 100644 index 000000000..213b88638 --- /dev/null +++ b/doc/dom/element/prototype/store/index.html @@ -0,0 +1,299 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#store + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#store +

    + + + + +
    +
    +
    +
    +
    +
    Element#store(key, value) → Element
    + + +

    Stores a key/value pair of custom metadata on the element.

    + +

    The metadata can later be retrieved with Element.retrieve.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/toggle/index.html b/doc/dom/element/prototype/toggle/index.html new file mode 100644 index 000000000..7a5261fb3 --- /dev/null +++ b/doc/dom/element/prototype/toggle/index.html @@ -0,0 +1,340 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#toggle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#toggle +

    + + + + +
    +
    +
    +
    +
    +
    Element#toggle() → Element
    + + +

    Toggles the visibility of element. Returns element.

    + +
    Examples
    + +
    <div id="welcome-message"></div>
    +<div id="error-message" style="display:none;"></div>
    + $('welcome-message').toggle();
    +// -> Element (and hides div#welcome-message)
    + $('error-message').toggle();
    +// -> Element (and displays div#error-message)
    +
    +
    + +

    Toggle multiple elements using Enumerable#each:

    + +
    ['error-message', 'welcome-message'].each(Element.toggle);
    +// -> ['error-message', 'welcome-message']
    +
    +
    + +

    Toggle multiple elements using Enumerable#invoke:

    + +
    $('error-message', 'welcome-message').invoke('toggle');
    +// -> [Element, Element]
    +
    +
    + +
    Notes
    + +

    Element.toggle cannot display elements hidden via CSS stylesheets. +Note that this is not a Prototype limitation but a consequence of how the +CSS display property works.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    + $('hidden-by-css').toggle(); // WONT' WORK!
    +// -> Element (div#hidden-by-css is still hidden!)
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/toggleclassname/index.html b/doc/dom/element/prototype/toggleclassname/index.html new file mode 100644 index 000000000..f176da0a6 --- /dev/null +++ b/doc/dom/element/prototype/toggleclassname/index.html @@ -0,0 +1,314 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#toggleClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#toggleClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element#toggleClassName(className) → Element
    + + +

    Toggles the presence of CSS class className on element.

    + +
    Examples
    + +
    <div id="mutsu" class="apple"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').hasClassName('fruit');
    +// -> false
    + $('mutsu').toggleClassName('fruit');
    +// -> element
    + $('mutsu').hasClassName('fruit');
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/undoclipping/index.html b/doc/dom/element/prototype/undoclipping/index.html new file mode 100644 index 000000000..3feda562c --- /dev/null +++ b/doc/dom/element/prototype/undoclipping/index.html @@ -0,0 +1,341 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#undoClipping + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#undoClipping +

    + + + + +
    +
    +
    +
    +
    +
    Element#undoClipping() → Element
    + + +

    Sets element's CSS overflow property back to the value it had +before Element.makeClipping was applied.

    + +
    Example
    + +
    <div id="framer">
    +  <img src="/assets/2007/1/14/chairs.jpg" alt="example" />
    +</div>
    +
    +
    + +

    Then:

    + +
    $('framer').undoClipping();
    +// -> Element (and sets the CSS overflow property to its original value).
    +
    +
    + +

    Another example:

    + +
    <a id="clipper" href="#">Click me to try it out.</a>
    + <div id="framer">
    +  <img src="/assets/2007/2/24/chairs_1.jpg" alt="example" />
    +</div>
    + <script type="text/javascript" charset="utf-8">
    +  var Example = {
    +    clip: function(){
    +      $('clipper').update('undo clipping!');
    +      $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +    },
    +    unClip: function(){
    +      $('clipper').update('clip!');
    +      $('framer').undoClipping();
    +    },
    +    toggleClip: function(event){
    +      if($('clipper').innerHTML == 'clip!') Example.clip();
    +      else Example.unClip();
    +      Event.stop(event);
    +    }
    +  };
    +  $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +  Event.observe('clipper', 'click', Example.toggleClip);
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/undopositioned/index.html b/doc/dom/element/prototype/undopositioned/index.html new file mode 100644 index 000000000..dc3fa0da3 --- /dev/null +++ b/doc/dom/element/prototype/undopositioned/index.html @@ -0,0 +1,302 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#undoPositioned + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#undoPositioned +

    + + + + +
    +
    +
    +
    +
    +
    Element#undoPositioned() → Element
    + + +

    Sets element back to the state it was in before +Element.makePositioned was applied to it.

    + +

    element's absolutely positioned children will now have their positions +set relatively to element's nearest ancestor with a CSS position of +'absolute', 'relative' or 'fixed'.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/up/index.html b/doc/dom/element/prototype/up/index.html new file mode 100644 index 000000000..e58f892e1 --- /dev/null +++ b/doc/dom/element/prototype/up/index.html @@ -0,0 +1,413 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#up + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#up +

    + + + + +
    +
    +
    +
    +
    +
    Element#up([expression[, index = 0]]) → Element
    Element#up([index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first ancestor (or the Nth ancestor, if index +is specified) that matches expression. If no expression is +provided, all ancestors are considered. If no ancestor matches these +criteria, undefined is returned.

    + +
    More information
    + +

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

    + +

    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 +(see Element.extended) allowing chaining:

    + +
    $(element).up(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's first ancestor is returned (this +is similar to calling parentNode except Element.up returns an already +extended element.

    + +

    If index is defined, element's corresponding ancestor is returned. +(This is equivalent to selecting an element from the array of elements +returned by the method Element.ancestors). Note that the first element +has an index of 0.

    + +

    If expression is defined, Element.up will return the first ancestor +that matches it.

    + +

    If both expression and index are defined, Element.up will collect +all the ancestors matching the given CSS expression and will return the +one at the specified index.

    + +

    In all of the above cases, if no descendant is found, undefined +will be returned.

    + +

    Examples

    + +
    <html>
    +  [...]
    +  <body>
    +    <ul id="fruits">
    +      <li id="apples" class="keeps-the-doctor-away">
    +        <ul>
    +          <li id="golden-delicious">Golden Delicious</li>
    +          <li id="mutsu" class="yummy">Mutsu</li>
    +          <li id="mcintosh" class="yummy">McIntosh</li>
    +          <li id="ida-red">Ida Red</li>
    +        </ul>
    +      </li>
    +    </ul>
    +  </body>
    +</html>
    +
    +
    + +

    Get the first ancestor of "#fruites":

    + +
    $('fruits').up();
    +// or:
    +$('fruits').up(0);
    +// -> body
    +
    +
    + +

    Get the third ancestor of "#mutsu":

    + +
    $('mutsu').up(2);
    +// -> ul#fruits
    +
    +
    + +

    Get the first ancestor of "#mutsu" with the node name "li":

    + +
    $('mutsu').up('li');
    +// -> li#apples
    +
    +
    + +

    Get the first ancestor of "#mutsu" with the class name +"keeps-the-doctor-away":

    + +
    $('mutsu').up('.keeps-the-doctor-away');
    +// -> li#apples
    +
    +
    + +

    Get the second ancestor of "#mutsu" with the node name "ul":

    + +
    $('mutsu').up('ul', 1);
    +// -> ul#fruits
    +
    +
    + +

    Try to get the first ancestor of "#mutsu" with the node name "div":

    + +
    $('mutsu').up('div');
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/update/index.html b/doc/dom/element/prototype/update/index.html new file mode 100644 index 000000000..b53b5027f --- /dev/null +++ b/doc/dom/element/prototype/update/index.html @@ -0,0 +1,391 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#update + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#update +

    + + + + +
    +
    +
    +
    +
    +
    Element#update([newContent]) → Element
    + + +

    Replaces the content of element with the newContent argument and +returns element.

    + +

    newContent may be in any of these forms:

    + +
      +
    • String: A string of HTML to be parsed and rendered
    • +
    • Element: An Element instance to insert
    • +
    • ...any object with a toElement method: The method is called and the resulting element used
    • +
    • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
    • +
    + +

    If newContent is omitted, the element's content is blanked out (i.e., +replaced with an empty string).

    + +

    If newContent is a string and contains one or more inline <script> +tags, the scripts are scheduled to be evaluated after a very brief pause +(using Function#defer) to allow the browser to finish updating the +DOM. Note that the scripts are evaluated in the scope of +String#evalScripts, not in the global scope, which has important +ramifications for your vars and functions. +See String#evalScripts for details.

    + +

    Note that this method allows seamless content update of table related +elements in Internet Explorer 6 and beyond.

    + +
    Examples
    + +
    <div id="fruits">carrot, eggplant and cucumber</div>
    +
    +
    + +

    Passing a regular string:

    + +
    $('fruits').update('kiwi, banana and apple');
    +// -> Element
    +$('fruits').innerHTML;
    +// -> 'kiwi, banana and apple'
    +
    +
    + +

    Clearing the element's content:

    + +
    $('fruits').update();
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '' (an empty string)
    +
    +
    + +

    And now inserting an HTML snippet:

    + +
    $('fruits').update('<p>Kiwi, banana <em>and</em> apple.</p>');
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '<p>Kiwi, banana <em>and</em> apple.</p>'
    +
    +
    + +

    ... with a <script> tag thrown in:

    + +
    $('fruits').update('<p>Kiwi, banana <em>and</em> apple.</p><script>alert("updated!")</script>');
    +// -> Element (and prints "updated!" in an alert dialog).
    +$('fruits').innerHTML;
    +// -> '<p>Kiwi, banana <em>and</em> apple.</p>'
    +
    +
    + +

    Relying on the toString() method:

    + +
    $('fruits').update(123);
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '123'
    +
    +
    + +

    Finally, you can do some pretty funky stuff by defining your own +toString() method on your custom objects:

    + +
    var Fruit = Class.create({
    +  initialize: function(fruit){
    +    this.fruit = fruit;
    +  },
    +  toString: function(){
    +    return 'I am a fruit and my name is "' + this.fruit + '".';
    +  }
    +});
    +var apple = new Fruit('apple');
    + $('fruits').update(apple);
    +$('fruits').innerHTML;
    +// -> 'I am a fruit and my name is "apple".'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/viewportoffset/index.html b/doc/dom/element/prototype/viewportoffset/index.html new file mode 100644 index 000000000..9d85438cf --- /dev/null +++ b/doc/dom/element/prototype/viewportoffset/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#viewportOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#viewportOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element#viewportOffset() → Array
    + + +

    Returns the X/Y coordinates of element relative to the viewport.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/visible/index.html b/doc/dom/element/prototype/visible/index.html new file mode 100644 index 000000000..e2ea44ee2 --- /dev/null +++ b/doc/dom/element/prototype/visible/index.html @@ -0,0 +1,336 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#visible + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#visible +

    + + + + +
    +
    +
    +
    +
    +
    Element#visible() → Boolean
    + + +

    Tells whether element is visible (i.e., whether its inline display +CSS property is set to none.

    + +
    Examples
    + +
    <div id="visible"></div>
    +<div id="hidden" style="display: none;"></div>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('visible').visible();
    +// -> true
    + $('hidden').visible();
    +// -> false
    +
    +
    + +
    Notes
    + +

    Styles applied via a CSS stylesheet are not taken into consideration. +Note that this is not a Prototype limitation, it is a CSS limitation.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('hidden-by-css').visible();
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/wrap/index.html b/doc/dom/element/prototype/wrap/index.html new file mode 100644 index 000000000..aa46a9787 --- /dev/null +++ b/doc/dom/element/prototype/wrap/index.html @@ -0,0 +1,370 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#wrap + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#wrap +

    + + + + +
    +
    +
    +
    +
    +
    Element#wrap(wrapper[, attributes]) → Element
    +
      +
    • + wrapper + (Element | String) + – An element to wrap element inside, or else a string representing the tag name of an element to be created. +
    • +
    • + attributes + (Object) + – A set of attributes to apply to the wrapper element. Refer to the Element constructor for usage. +
    • +
    + + +

    Wraps an element inside another, then returns the wrapper.

    + +

    If the given element exists on the page, Element.wrap will wrap it in +place — its position will remain the same.

    + +

    The wrapper argument can be either an existing Element _or_ a +string representing the tag name of an element to be created. The optional +attributes argument can contain a list of attribute/value pairs that +will be set on the wrapper using Element.writeAttribute.

    + +
    Examples
    + +

    Original HTML:

    + +
    <table id="data">
    +  <tr>
    +    <th>Foo</th>
    +    <th>Bar</th>
    +  </tr>
    +  <tr>
    +    <td>1</td>
    +    <td>2</td>
    +  </tr>
    +</table>
    +
    +
    + +

    JavaScript:

    + +
    // approach 1:
    +var div = new Element('div', { 'class': 'table-wrapper' });
    +$('data').wrap(div);
    + // approach 2:
    +$('data').wrap('div', { 'class': 'table-wrapper' });
    + // Both examples are equivalent &mdash; they return the DIV.
    +
    +
    + +

    Resulting HTML:

    + +
    <div class="table-wrapper">
    +  <table id="data">
    +    <tr>
    +      <th>Foo</th>
    +      <th>Bar</th>
    +    </tr>
    +    <tr>
    +      <td>1</td>
    +      <td>2</td>
    +    </tr>
    +  </table>
    +</div>
    +
    +
    + +
    Warning
    + +

    Using Element.wrap as an instance method (e.g., $('foo').wrap('p')) +causes errors in Internet Explorer when used on textarea elements. The +wrap property is reserved on textarea's as a proprietary extension to +HTML. As a workaround, use the generic version instead +(Element.wrap('foo', 'p')).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/prototype/writeattribute/index.html b/doc/dom/element/prototype/writeattribute/index.html new file mode 100644 index 000000000..3bfbd5047 --- /dev/null +++ b/doc/dom/element/prototype/writeattribute/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element#writeAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Element#writeAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element#writeAttribute(attribute[, value = true]) → Element
    Element#writeAttribute(attributes) → Element
    + + +

    Adds, specifies or removes attributes passed as either a hash or a +name/value pair.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/readattribute/index.html b/doc/dom/element/readattribute/index.html new file mode 100644 index 000000000..6ce6edd53 --- /dev/null +++ b/doc/dom/element/readattribute/index.html @@ -0,0 +1,321 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.readAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.readAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element.readAttribute(element, attributeName) → String | null
    + + +

    Returns the value of element's attribute or null if attribute has +not been specified.

    + +

    This method serves two purposes. First it acts as a simple wrapper around +getAttribute which isn't a "real" function in Safari and Internet +Explorer (it doesn't have .apply or .call for instance). Secondly, it +cleans up the horrible mess Internet Explorer makes when handling +attributes.

    + +
    Examples
    + +
    <a id="tag" href="/tags/prototype" rel="tag" title="view related bookmarks." my_widget="some info.">Prototype</a>
    +
    +
    + +

    Then:

    + +
    $('tag').readAttribute('href');
    +// -> '/tags/prototype'
    + $('tag').readAttribute('title');
    +// -> 'view related bookmarks.'
    + $('tag').readAttribute('my_widget');
    +// -> 'some info.'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/recursivelycollect/index.html b/doc/dom/element/recursivelycollect/index.html new file mode 100644 index 000000000..69cfaf746 --- /dev/null +++ b/doc/dom/element/recursivelycollect/index.html @@ -0,0 +1,334 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.recursivelyCollect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.recursivelyCollect +

    + + + + +
    +
    +
    +
    +
    +
    Element.recursivelyCollect(element, property) → [Element…]
    + + +

    Recursively collects elements whose relationship to element is +specified by property. property has to be a property (a method +won't do!) of element that points to a single DOM node (e.g., +nextSibling or parentNode).

    + +
    More information
    + +

    This method is used internally by Element.ancestors, +Element.descendants, Element.nextSiblings, +Element.previousSiblings and Element.siblings which offer really +convenient way to grab elements, so directly accessing +Element.recursivelyCollect should seldom be needed. However, if you +are after something out of the ordinary, it is the way to go.

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <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>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('fruits').recursivelyCollect('firstChild');
    +// -> [li#apples, ul#list-of-apples, li#golden-delicious, p]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/relativize/index.html b/doc/dom/element/relativize/index.html new file mode 100644 index 000000000..6d112ac46 --- /dev/null +++ b/doc/dom/element/relativize/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.relativize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.relativize +

    + + + + +
    +
    +
    +
    +
    +
    Element.relativize(element) → Element
    + + +

    Turns element into a relatively-positioned element without changing +its position in the page layout.

    + +

    Used to undo a call to Element.absolutize.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/remove/index.html b/doc/dom/element/remove/index.html new file mode 100644 index 000000000..7fae5f739 --- /dev/null +++ b/doc/dom/element/remove/index.html @@ -0,0 +1,329 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.remove + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.remove +

    + + + + +
    +
    +
    +
    +
    +
    Element.remove(element) → Element
    + + +

    Completely removes element from the document and returns it.

    + +

    If you would rather just hide the element and keep it around for further +use, try Element.hide instead.

    + +
    Examples
    + +
    // Before:
    +<ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('mutsu').remove();
    +// -> Element (and removes li#mutsu)
    +
    +
    + +

    The resulting HTML:

    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/removeclassname/index.html b/doc/dom/element/removeclassname/index.html new file mode 100644 index 000000000..038fc575c --- /dev/null +++ b/doc/dom/element/removeclassname/index.html @@ -0,0 +1,314 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.removeClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.removeClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element.removeClassName(element, className) → Element
    + + +

    Removes CSS class className from element.

    + +
    Examples
    + +

    Assuming this HTML:

    + +
    <div id="mutsu" class="apple fruit food"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').removeClassName('food');
    +// -> Element
    + $('mutsu').classNames;
    +// -> 'apple fruit'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/replace/index.html b/doc/dom/element/replace/index.html new file mode 100644 index 000000000..2d7ef8ca5 --- /dev/null +++ b/doc/dom/element/replace/index.html @@ -0,0 +1,366 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.replace + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.replace +

    + + + + +
    +
    +
    +
    +
    +
    Element.replace(element[, newContent]) → Element
    + + +

    Replaces element itself with newContent and returns element.

    + +

    Keep in mind that this method returns the element that has just been +removed — not the element that took its place.

    + +

    newContent can be either plain text, an HTML snippet or any JavaScript +object which has a toString() method.

    + +

    If newContent contains any <script> tags, these will be evaluated +after element has been replaced (Element.replace internally calls +String#evalScripts).

    + +

    Note that if no argument is provided, Element.replace will simply +clear element of its content. However, using Element.remove to do so +is both faster and more standard compliant.

    + +
    Examples
    + +
    <div id="food">
    +  <div id="fruits">
    +    <p id="first">Kiwi, banana <em>and</em> apple.</p>
    +  </div>
    +</div>
    +
    +
    + +

    Passing an HTML snippet:

    + +
    $('first').replace('<ul id="favorite"><li>kiwi</li><li>banana</li><li>apple</li></ul>');
    +// -> Element (p#first)
    + $('fruits').innerHTML;
    +// -> '<ul id="favorite"><li>kiwi</li><li>banana</li><li>apple</li></ul>'
    +
    +
    + +

    Again, with a <script> tag thrown in:

    + +
    $('favorite').replace('<p id="still-first">Melon, oranges <em>and</em> grapes.</p><script>alert("removed!")</script>');
    +// -> Element (ul#favorite) and prints "removed!" in an alert dialog.
    + $('fruits').innerHTML;
    +// -> '<p id="still-first">Melon, oranges <em>and</em> grapes.</p>'
    +
    +
    + +

    With plain text:

    + +
    $('still-first').replace('Melon, oranges and grapes.');
    +// -> Element (p#still-first)
    + $('fruits').innerHTML;
    +// -> 'Melon, oranges and grapes.'
    +
    +
    + +

    Finally, relying on the toString() method:

    + +
    $('fruits').replace(123);
    +// -> Element
    + $('food').innerHTML;
    +// -> '123'
    +
    +
    + +
    Warning
    + +

    Using Element.replace as an instance method (e.g., +$('foo').replace('<p>Bar</p>')) causes errors in Opera 9 when used on +input elements. The replace property is reserved on input elements +as part of Web Forms 2. +As a workaround, use the generic version instead +(Element.replace('foo', '<p>Bar</p>')).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/retrieve/index.html b/doc/dom/element/retrieve/index.html new file mode 100644 index 000000000..f1eafe03d --- /dev/null +++ b/doc/dom/element/retrieve/index.html @@ -0,0 +1,300 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.retrieve + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.retrieve +

    + + + + +
    +
    +
    +
    +
    +
    Element.retrieve(element, key[, defaultValue]) → ?
    + + +

    Retrieves custom metadata set on element with Element.store.

    + +

    If the value is undefined and defaultValue is given, it will be +stored on the element as its new value for that key, then returned.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/scrollto/index.html b/doc/dom/element/scrollto/index.html new file mode 100644 index 000000000..588abf9d1 --- /dev/null +++ b/doc/dom/element/scrollto/index.html @@ -0,0 +1,308 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.scrollTo + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.scrollTo +

    + + + + +
    +
    +
    +
    +
    +
    Element.scrollTo(element) → Element
    + + +

    Scrolls the window so that element appears at the top of the viewport.

    + +

    This has a similar effect than what would be achieved using +HTML anchors +(except the browser's history is not modified).

    + +
    Example
    + +
    $(element).scrollTo();
    +// -> Element
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/select/index.html b/doc/dom/element/select/index.html new file mode 100644 index 000000000..5b4f8f7f8 --- /dev/null +++ b/doc/dom/element/select/index.html @@ -0,0 +1,356 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.select +

    + + + + +
    +
    +
    +
    +
    +
    Element.select(element, expression...) → [Element…]
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Takes an arbitrary number of CSS selectors and returns an array of +descendants of element that match any of them.

    + +

    This method is very similar to $$ but can be used within the context +of one element, rather than the whole document. The supported CSS syntax +is identical, so please refer to the $$ docs for details.

    + +
    Examples
    + +
    <ul id="fruits">
    +  <li id="apples">
    +    <h3 title="yummy!">Apples</h3>
    +    <ul id="list-of-apples">
    +      <li id="golden-delicious" title="yummy!" >Golden Delicious</li>
    +      <li id="mutsu" title="yummy!">Mutsu</li>
    +      <li id="mcintosh">McIntosh</li>
    +      <li id="ida-red">Ida Red</li>
    +    </ul>
    +    <p id="saying">An apple a day keeps the doctor away.</p>
    +  </li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('apples').select('[title="yummy!"]');
    +// -> [h3, li#golden-delicious, li#mutsu]
    + $('apples').select( 'p#saying', 'li[title="yummy!"]');
    +// -> [li#golden-delicious, li#mutsu,  p#saying]
    + $('apples').select('[title="disgusting!"]');
    +// -> []
    +
    +
    + +
    Tip
    + +

    Element.select can be used as a pleasant alternative to the native +method getElementsByTagName:

    + +
    var nodes  = $A(someUL.getElementsByTagName('li')).map(Element.extend);
    +var nodes2 = someUL.select('li');
    +
    +
    + +

    In the first example, you must explicitly convert the result set to an +Array (so that Prototype's Enumerable methods can be used) and +must manually call Element.extend on each node (so that custom +instance methods can be used on the nodes). Element.select takes care +of both concerns on its own.

    + +

    If you're using 1.6 or above (and the performance optimizations therein), +the speed difference between these two examples is negligible.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/setopacity/index.html b/doc/dom/element/setopacity/index.html new file mode 100644 index 000000000..066af0c00 --- /dev/null +++ b/doc/dom/element/setopacity/index.html @@ -0,0 +1,313 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.setOpacity + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.setOpacity +

    + + + + +
    +
    +
    +
    +
    +
    Element.setOpacity(element, opacity) → [Element…]
    + + +

    Sets the visual opacity of an element while working around inconsistencies +in various browsers. The opacity argument should be a floating point +number, where the value of 0 is fully transparent and 1 is fully opaque.

    + +

    Element.setStyle method uses Element.setOpacity internally when needed.

    + +
    Examples
    + +
    var element = $('myelement');
    +// set to 50% transparency
    +element.setOpacity(0.5);
    + // these are equivalent, but allow for setting more than
    +// one CSS property at once:
    +element.setStyle({ opacity: 0.5 });
    +element.setStyle("opacity: 0.5");
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/setstyle/index.html b/doc/dom/element/setstyle/index.html new file mode 100644 index 000000000..bd8fa9c33 --- /dev/null +++ b/doc/dom/element/setstyle/index.html @@ -0,0 +1,334 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.setStyle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.setStyle +

    + + + + +
    +
    +
    +
    +
    +
    Element.setStyle(element, styles) → Element
    + + +

    Modifies element's CSS style properties. Styles are passed as a hash of +property-value pairs in which the properties are specified in their +camelized form.

    + +
    Examples
    + +
    $(element).setStyle({
    +  backgroundColor: '#900',
    +  fontSize: '12px'
    +});
    +// -> Element
    +
    +
    + +
    Notes
    + +

    The method transparently deals with browser inconsistencies for float +(however, as float is a reserved keyword, you must either escape it or +use cssFloat instead) and opacity (which accepts values between 0 +-fully transparent- and 1 -fully opaque-). You can safely use either of +the following across all browsers:

    + +
    $(element).setStyle({
    +  cssFloat: 'left',
    +  opacity: 0.5
    +});
    +// -> Element
    + $(element).setStyle({
    +  'float': 'left', // notice how float is surrounded by single quotes
    +  opacity: 0.5
    +});
    +// -> Element
    +
    +
    + +

    Not all CSS shorthand properties are supported. You may only use the CSS +properties described in the +Document Object Model (DOM) Level 2 Style Specification.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/show/index.html b/doc/dom/element/show/index.html new file mode 100644 index 000000000..22e8ae79b --- /dev/null +++ b/doc/dom/element/show/index.html @@ -0,0 +1,339 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.show + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.show +

    + + + + +
    +
    +
    +
    +
    +
    Element.show(element) → Element
    + + +

    Removes display: none on element. Returns element.

    + +
    Examples
    + +

    Show a single element:

    + +
    <div id="error-message" style="display:none;"></div>
    + $('error-message').show();
    +// -> Element (and displays div#error-message)
    +
    +
    + +

    Show multiple elements using Enumerable#each:

    + +
    ['content', 'navigation', 'footer'].each(Element.show);
    +// -> ['content', 'navigation', 'footer']
    +
    +
    + +

    Show multiple elements using Enumerable#invoke:

    + +
    $('content', 'navigation', 'footer').invoke('show');
    +// -> [Element, Element, Element]
    +
    +
    + +
    Notes
    + +

    Element.show cannot display elements hidden via CSS stylesheets. +Note that this is not a Prototype limitation but a consequence of how the +CSS display property works.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    + $('hidden-by-css').show(); // DOES NOT WORK!
    +// -> Element (div#error-message is still hidden!)
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/siblings/index.html b/doc/dom/element/siblings/index.html new file mode 100644 index 000000000..d06c999b8 --- /dev/null +++ b/doc/dom/element/siblings/index.html @@ -0,0 +1,326 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.siblings + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.siblings +

    + + + + +
    +
    +
    +
    +
    +
    Element.siblings(element) → [Element…]
    + + +

    Collects all of element's siblings and returns them as an Array of +elements.

    + +

    Two elements are siblings if they have the same parent. So for example, +the head and body elements are siblings (their parent is the html +element).

    + +

    The returned Array reflects the siblings' order in the document (e.g. +an index of 0 refers to element's topmost sibling).

    + +

    Note that all of Prototype's DOM traversal methods ignore text nodes and +return element nodes only.

    + +
    Examples
    + +
    <ul>
    +  <li id="golden-delicious">Golden Delicious</li>
    +  <li id="mutsu">Mutsu</li>
    +  <li id="mcintosh">McIntosh</li>
    +  <li id="ida-red">Ida Red</li>
    +</ul>
    +
    +
    + +

    Then:

    + +
    $('mutsu').siblings();
    +// -> [li#golden-delicious, li#mcintosh, li#ida-red]
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/stopobserving/index.html b/doc/dom/element/stopobserving/index.html new file mode 100644 index 000000000..689379171 --- /dev/null +++ b/doc/dom/element/stopobserving/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.stopObserving + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.stopObserving +

    + + + + +
    +
    +
    +
    +
    +
    Element.stopObserving(element[, eventName[, handler]]) → Element
    + + +

    See Event.stopObserving.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/store/index.html b/doc/dom/element/store/index.html new file mode 100644 index 000000000..02186b758 --- /dev/null +++ b/doc/dom/element/store/index.html @@ -0,0 +1,299 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.store + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.store +

    + + + + +
    +
    +
    +
    +
    +
    Element.store(element, key, value) → Element
    + + +

    Stores a key/value pair of custom metadata on the element.

    + +

    The metadata can later be retrieved with Element.retrieve.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/toggle/index.html b/doc/dom/element/toggle/index.html new file mode 100644 index 000000000..bac7757d4 --- /dev/null +++ b/doc/dom/element/toggle/index.html @@ -0,0 +1,340 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.toggle + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.toggle +

    + + + + +
    +
    +
    +
    +
    +
    Element.toggle(element) → Element
    + + +

    Toggles the visibility of element. Returns element.

    + +
    Examples
    + +
    <div id="welcome-message"></div>
    +<div id="error-message" style="display:none;"></div>
    + $('welcome-message').toggle();
    +// -> Element (and hides div#welcome-message)
    + $('error-message').toggle();
    +// -> Element (and displays div#error-message)
    +
    +
    + +

    Toggle multiple elements using Enumerable#each:

    + +
    ['error-message', 'welcome-message'].each(Element.toggle);
    +// -> ['error-message', 'welcome-message']
    +
    +
    + +

    Toggle multiple elements using Enumerable#invoke:

    + +
    $('error-message', 'welcome-message').invoke('toggle');
    +// -> [Element, Element]
    +
    +
    + +
    Notes
    + +

    Element.toggle cannot display elements hidden via CSS stylesheets. +Note that this is not a Prototype limitation but a consequence of how the +CSS display property works.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    + $('hidden-by-css').toggle(); // WONT' WORK!
    +// -> Element (div#hidden-by-css is still hidden!)
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/toggleclassname/index.html b/doc/dom/element/toggleclassname/index.html new file mode 100644 index 000000000..709fd0035 --- /dev/null +++ b/doc/dom/element/toggleclassname/index.html @@ -0,0 +1,314 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.toggleClassName + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.toggleClassName +

    + + + + +
    +
    +
    +
    +
    +
    Element.toggleClassName(element, className) → Element
    + + +

    Toggles the presence of CSS class className on element.

    + +
    Examples
    + +
    <div id="mutsu" class="apple"></div>
    +
    +
    + +

    Then:

    + +
    $('mutsu').hasClassName('fruit');
    +// -> false
    + $('mutsu').toggleClassName('fruit');
    +// -> element
    + $('mutsu').hasClassName('fruit');
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/undoclipping/index.html b/doc/dom/element/undoclipping/index.html new file mode 100644 index 000000000..3e8fd0fa7 --- /dev/null +++ b/doc/dom/element/undoclipping/index.html @@ -0,0 +1,341 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.undoClipping + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.undoClipping +

    + + + + +
    +
    +
    +
    +
    +
    Element.undoClipping(element) → Element
    + + +

    Sets element's CSS overflow property back to the value it had +before Element.makeClipping was applied.

    + +
    Example
    + +
    <div id="framer">
    +  <img src="/assets/2007/1/14/chairs.jpg" alt="example" />
    +</div>
    +
    +
    + +

    Then:

    + +
    $('framer').undoClipping();
    +// -> Element (and sets the CSS overflow property to its original value).
    +
    +
    + +

    Another example:

    + +
    <a id="clipper" href="#">Click me to try it out.</a>
    + <div id="framer">
    +  <img src="/assets/2007/2/24/chairs_1.jpg" alt="example" />
    +</div>
    + <script type="text/javascript" charset="utf-8">
    +  var Example = {
    +    clip: function(){
    +      $('clipper').update('undo clipping!');
    +      $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +    },
    +    unClip: function(){
    +      $('clipper').update('clip!');
    +      $('framer').undoClipping();
    +    },
    +    toggleClip: function(event){
    +      if($('clipper').innerHTML == 'clip!') Example.clip();
    +      else Example.unClip();
    +      Event.stop(event);
    +    }
    +  };
    +  $('framer').makeClipping().setStyle({width: '100px', height: '100px'});
    +  Event.observe('clipper', 'click', Example.toggleClip);
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/undopositioned/index.html b/doc/dom/element/undopositioned/index.html new file mode 100644 index 000000000..3c573ed80 --- /dev/null +++ b/doc/dom/element/undopositioned/index.html @@ -0,0 +1,302 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.undoPositioned + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.undoPositioned +

    + + + + +
    +
    +
    +
    +
    +
    Element.undoPositioned(element) → Element
    + + +

    Sets element back to the state it was in before +Element.makePositioned was applied to it.

    + +

    element's absolutely positioned children will now have their positions +set relatively to element's nearest ancestor with a CSS position of +'absolute', 'relative' or 'fixed'.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/up/index.html b/doc/dom/element/up/index.html new file mode 100644 index 000000000..83f05868b --- /dev/null +++ b/doc/dom/element/up/index.html @@ -0,0 +1,413 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.up + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.up +

    + + + + +
    +
    +
    +
    +
    +
    Element.up(element[, expression[, index = 0]]) → Element
    Element.up(element[, index = 0]) → Element
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Returns element's first ancestor (or the Nth ancestor, if index +is specified) that matches expression. If no expression is +provided, all ancestors are considered. If no ancestor matches these +criteria, undefined is returned.

    + +
    More information
    + +

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

    + +

    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 +(see Element.extended) allowing chaining:

    + +
    $(element).up(1).next('li', 2).hide();
    +
    +
    + +

    Walking the DOM has never been that easy!

    + +
    Arguments
    + +

    If no arguments are passed, element's first ancestor is returned (this +is similar to calling parentNode except Element.up returns an already +extended element.

    + +

    If index is defined, element's corresponding ancestor is returned. +(This is equivalent to selecting an element from the array of elements +returned by the method Element.ancestors). Note that the first element +has an index of 0.

    + +

    If expression is defined, Element.up will return the first ancestor +that matches it.

    + +

    If both expression and index are defined, Element.up will collect +all the ancestors matching the given CSS expression and will return the +one at the specified index.

    + +

    In all of the above cases, if no descendant is found, undefined +will be returned.

    + +

    Examples

    + +
    <html>
    +  [...]
    +  <body>
    +    <ul id="fruits">
    +      <li id="apples" class="keeps-the-doctor-away">
    +        <ul>
    +          <li id="golden-delicious">Golden Delicious</li>
    +          <li id="mutsu" class="yummy">Mutsu</li>
    +          <li id="mcintosh" class="yummy">McIntosh</li>
    +          <li id="ida-red">Ida Red</li>
    +        </ul>
    +      </li>
    +    </ul>
    +  </body>
    +</html>
    +
    +
    + +

    Get the first ancestor of "#fruites":

    + +
    $('fruits').up();
    +// or:
    +$('fruits').up(0);
    +// -> body
    +
    +
    + +

    Get the third ancestor of "#mutsu":

    + +
    $('mutsu').up(2);
    +// -> ul#fruits
    +
    +
    + +

    Get the first ancestor of "#mutsu" with the node name "li":

    + +
    $('mutsu').up('li');
    +// -> li#apples
    +
    +
    + +

    Get the first ancestor of "#mutsu" with the class name +"keeps-the-doctor-away":

    + +
    $('mutsu').up('.keeps-the-doctor-away');
    +// -> li#apples
    +
    +
    + +

    Get the second ancestor of "#mutsu" with the node name "ul":

    + +
    $('mutsu').up('ul', 1);
    +// -> ul#fruits
    +
    +
    + +

    Try to get the first ancestor of "#mutsu" with the node name "div":

    + +
    $('mutsu').up('div');
    +// -> undefined
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/update/index.html b/doc/dom/element/update/index.html new file mode 100644 index 000000000..c9b5e7dd5 --- /dev/null +++ b/doc/dom/element/update/index.html @@ -0,0 +1,391 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.update + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.update +

    + + + + +
    +
    +
    +
    +
    +
    Element.update(element[, newContent]) → Element
    + + +

    Replaces the content of element with the newContent argument and +returns element.

    + +

    newContent may be in any of these forms:

    + +
      +
    • String: A string of HTML to be parsed and rendered
    • +
    • Element: An Element instance to insert
    • +
    • ...any object with a toElement method: The method is called and the resulting element used
    • +
    • ...any object with a toHTML method: The method is called and the resulting HTML string +is parsed and rendered
    • +
    + +

    If newContent is omitted, the element's content is blanked out (i.e., +replaced with an empty string).

    + +

    If newContent is a string and contains one or more inline <script> +tags, the scripts are scheduled to be evaluated after a very brief pause +(using Function#defer) to allow the browser to finish updating the +DOM. Note that the scripts are evaluated in the scope of +String#evalScripts, not in the global scope, which has important +ramifications for your vars and functions. +See String#evalScripts for details.

    + +

    Note that this method allows seamless content update of table related +elements in Internet Explorer 6 and beyond.

    + +
    Examples
    + +
    <div id="fruits">carrot, eggplant and cucumber</div>
    +
    +
    + +

    Passing a regular string:

    + +
    $('fruits').update('kiwi, banana and apple');
    +// -> Element
    +$('fruits').innerHTML;
    +// -> 'kiwi, banana and apple'
    +
    +
    + +

    Clearing the element's content:

    + +
    $('fruits').update();
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '' (an empty string)
    +
    +
    + +

    And now inserting an HTML snippet:

    + +
    $('fruits').update('<p>Kiwi, banana <em>and</em> apple.</p>');
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '<p>Kiwi, banana <em>and</em> apple.</p>'
    +
    +
    + +

    ... with a <script> tag thrown in:

    + +
    $('fruits').update('<p>Kiwi, banana <em>and</em> apple.</p><script>alert("updated!")</script>');
    +// -> Element (and prints "updated!" in an alert dialog).
    +$('fruits').innerHTML;
    +// -> '<p>Kiwi, banana <em>and</em> apple.</p>'
    +
    +
    + +

    Relying on the toString() method:

    + +
    $('fruits').update(123);
    +// -> Element
    +$('fruits').innerHTML;
    +// -> '123'
    +
    +
    + +

    Finally, you can do some pretty funky stuff by defining your own +toString() method on your custom objects:

    + +
    var Fruit = Class.create({
    +  initialize: function(fruit){
    +    this.fruit = fruit;
    +  },
    +  toString: function(){
    +    return 'I am a fruit and my name is "' + this.fruit + '".';
    +  }
    +});
    +var apple = new Fruit('apple');
    + $('fruits').update(apple);
    +$('fruits').innerHTML;
    +// -> 'I am a fruit and my name is "apple".'
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/viewportoffset/index.html b/doc/dom/element/viewportoffset/index.html new file mode 100644 index 000000000..360baa1ec --- /dev/null +++ b/doc/dom/element/viewportoffset/index.html @@ -0,0 +1,297 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.viewportOffset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.viewportOffset +

    + + + + +
    +
    +
    +
    +
    +
    Element.viewportOffset(element) → Array
    + + +

    Returns the X/Y coordinates of element relative to the viewport.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/visible/index.html b/doc/dom/element/visible/index.html new file mode 100644 index 000000000..fe72e1c9f --- /dev/null +++ b/doc/dom/element/visible/index.html @@ -0,0 +1,336 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.visible + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.visible +

    + + + + +
    +
    +
    +
    +
    +
    Element.visible(element) → Boolean
    + + +

    Tells whether element is visible (i.e., whether its inline display +CSS property is set to none.

    + +
    Examples
    + +
    <div id="visible"></div>
    +<div id="hidden" style="display: none;"></div>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('visible').visible();
    +// -> true
    + $('hidden').visible();
    +// -> false
    +
    +
    + +
    Notes
    + +

    Styles applied via a CSS stylesheet are not taken into consideration. +Note that this is not a Prototype limitation, it is a CSS limitation.

    + +
    <style>
    +  #hidden-by-css {
    +    display: none;
    +  }
    +</style>
    + [...]
    + <div id="hidden-by-css"></div>
    +
    +
    + +

    And the associated JavaScript:

    + +
    $('hidden-by-css').visible();
    +// -> true
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/wrap/index.html b/doc/dom/element/wrap/index.html new file mode 100644 index 000000000..6292077e7 --- /dev/null +++ b/doc/dom/element/wrap/index.html @@ -0,0 +1,370 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.wrap + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.wrap +

    + + + + +
    +
    +
    +
    +
    +
    Element.wrap(element, wrapper[, attributes]) → Element
    +
      +
    • + wrapper + (Element | String) + – An element to wrap element inside, or else a string representing the tag name of an element to be created. +
    • +
    • + attributes + (Object) + – A set of attributes to apply to the wrapper element. Refer to the Element constructor for usage. +
    • +
    + + +

    Wraps an element inside another, then returns the wrapper.

    + +

    If the given element exists on the page, Element.wrap will wrap it in +place — its position will remain the same.

    + +

    The wrapper argument can be either an existing Element _or_ a +string representing the tag name of an element to be created. The optional +attributes argument can contain a list of attribute/value pairs that +will be set on the wrapper using Element.writeAttribute.

    + +
    Examples
    + +

    Original HTML:

    + +
    <table id="data">
    +  <tr>
    +    <th>Foo</th>
    +    <th>Bar</th>
    +  </tr>
    +  <tr>
    +    <td>1</td>
    +    <td>2</td>
    +  </tr>
    +</table>
    +
    +
    + +

    JavaScript:

    + +
    // approach 1:
    +var div = new Element('div', { 'class': 'table-wrapper' });
    +$('data').wrap(div);
    + // approach 2:
    +$('data').wrap('div', { 'class': 'table-wrapper' });
    + // Both examples are equivalent &mdash; they return the DIV.
    +
    +
    + +

    Resulting HTML:

    + +
    <div class="table-wrapper">
    +  <table id="data">
    +    <tr>
    +      <th>Foo</th>
    +      <th>Bar</th>
    +    </tr>
    +    <tr>
    +      <td>1</td>
    +      <td>2</td>
    +    </tr>
    +  </table>
    +</div>
    +
    +
    + +
    Warning
    + +

    Using Element.wrap as an instance method (e.g., $('foo').wrap('p')) +causes errors in Internet Explorer when used on textarea elements. The +wrap property is reserved on textarea's as a proprietary extension to +HTML. As a workaround, use the generic version instead +(Element.wrap('foo', 'p')).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/element/writeattribute/index.html b/doc/dom/element/writeattribute/index.html new file mode 100644 index 000000000..c7330831b --- /dev/null +++ b/doc/dom/element/writeattribute/index.html @@ -0,0 +1,298 @@ + + + + + Prototype v1.7_rc1 API documentation | Element.writeAttribute + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Element.writeAttribute +

    + + + + +
    +
    +
    +
    +
    +
    Element.writeAttribute(element, attribute[, value = true]) → Element
    Element.writeAttribute(element, attributes) → Element
    + + +

    Adds, specifies or removes attributes passed as either a hash or a +name/value pair.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/element/index.html b/doc/dom/event/element/index.html new file mode 100644 index 000000000..845c6a09d --- /dev/null +++ b/doc/dom/event/element/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.element + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Event.element +

    + + + + +
    +
    +
    +
    +
    +
    Event.element(event) → Element
    +
      +
    • + event + (Event) + – An Event object +
    • +
    + + +

    Returns the DOM element on which the event occurred. This method +is deprecated, use Event.findElement instead.

    + +
    Example
    + +

    Here's a simple bit of code which hides any paragraph when directly clicked.

    + +
    document.observe('click', function(event) {
    +  var element = Event.element(event);
    +  if ('P' == element.tagName)
    +    element.hide();
    +});
    +
    +
    + +
    See also
    + +

    There is a subtle distinction between this function and +Event.findElement.

    + +
    Note for Prototype 1.5.0
    + +

    Note that prior to version 1.5.1, if the browser does not support +native DOM extensions (see the Element section for further details), +the element returned by Event.element might very well +not be extended. If you intend to use methods from Element.Methods +on it, you need to wrap the call in the $ function like so:

    + +
    document.observe('click', function(event) {
    +  var element = $(Event.element(event));
    +  // ...
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/extend/index.html b/doc/dom/event/extend/index.html new file mode 100644 index 000000000..3a0144d6c --- /dev/null +++ b/doc/dom/event/extend/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.extend +

    + + + + +
    +
    +
    +
    +
    +
    Event.extend(event) → Event
    + + +

    Extends event with all of the methods contained in Event.Methods.

    + +

    Note that all events inside handlers that were registered using +Event.observe or Element.observe will be extended automatically.

    + +

    You need only call Event.extend manually if you register a handler a +different way (e.g., the onclick attribute). We really can't encourage +that sort of thing, though.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/findelement/index.html b/doc/dom/event/findelement/index.html new file mode 100644 index 000000000..ae6db290a --- /dev/null +++ b/doc/dom/event/findelement/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.findElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.findElement +

    + + + + +
    +
    +
    +
    +
    +
    Event.findElement(event[, expression]) → Element
    +
      +
    • + event + (Event) + – An Event object +
    • +
    • + expression + (String) + – An optional CSS selector +
    • +
    + + +

    Returns the first DOM element that matches a given CSS selector — +starting with the element on which the event occurred, then moving up +its ancestor chain. If expression is not given, the element which fired +the event is returned.

    + +

    *If no matching element is found, the document itself (HTMLDocument node) +is returned.*

    + +
    Example
    + +

    Here's a simple code that lets you click everywhere on the page and hides +the closest-fitting paragraph around your click (if any).

    + +
    document.observe('click', function(event) {
    +  var element = Event.findElement(event, 'p');
    +  if (element != document)
    +    $(element).hide();
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/fire/index.html b/doc/dom/event/fire/index.html new file mode 100644 index 000000000..718a2a9bc --- /dev/null +++ b/doc/dom/event/fire/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.fire + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.fire +

    + + + + +
    +
    +
    +
    +
    +
    Event.fire(element, eventName[, memo[, bubble = true]]) → Event
    +
      +
    • + memo + (?) + – Metadata for the event. Will be accessible through the event's memo property. +
    • +
    • + bubble + (Boolean) + – Whether the event will bubble. +
    • +
    + + +

    Fires a custom event of name eventName with element as its target.

    + +

    Custom events must include a colon (:) in their names.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/handler/index.html b/doc/dom/event/handler/index.html new file mode 100644 index 000000000..2e12a7611 --- /dev/null +++ b/doc/dom/event/handler/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.Handler + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Event.Handler +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Creates an observer on an element that listens for a particular event on +that element's descendants, optionally filtering by a CSS selector.

    + +

    This class simplifies the common "event delegation" pattern, in which one +avoids adding an observer to a number of individual elements and instead +listens on a common ancestor element.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance properties

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/dom/event/handler/new/index.html b/doc/dom/event/handler/new/index.html new file mode 100644 index 000000000..80bc4b9d1 --- /dev/null +++ b/doc/dom/event/handler/new/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | new Event.Handler + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Event.Handler +

    + + + + +
    +
    +
    +
    +
    +
    new(element, eventName[, selector], callback)
    +
      +
    • + element + (Element) + – The element to listen on. +
    • +
    • + eventName + (String) + – An event to listen for. Can be a standard browser event or a custom event. +
    • +
    • + selector + (String) + – A CSS selector. If specified, will call callback only when it can find an element that matches selector somewhere in the ancestor chain between the event's target element and the given element. +
    • +
    • + callback + (Function) + – The event handler function. Should expect two arguments: the event object and the element that received the event. (If selector was given, this element will be the one that satisfies the criteria described just above; if not, it will be the one specified in the element argument). +
    • +
    + + +

    Instantiates an Event.Handler. Will not begin observing until +Event.Handler#start is called.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/handler/prototype/start/index.html b/doc/dom/event/handler/prototype/start/index.html new file mode 100644 index 000000000..f59c2f2d2 --- /dev/null +++ b/doc/dom/event/handler/prototype/start/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.Handler#start + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Event.Handler#start +

    + + + + +
    +
    +
    +
    +
    +
    Event.Handler#start → Event.Handler
    + + +

    Starts listening for events. Returns itself.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/handler/prototype/stop/index.html b/doc/dom/event/handler/prototype/stop/index.html new file mode 100644 index 000000000..c7310719c --- /dev/null +++ b/doc/dom/event/handler/prototype/stop/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.Handler#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property Event.Handler#stop +

    + + + + +
    +
    +
    +
    +
    +
    Event.Handler#stop → Event.Handler
    + + +

    Stops listening for events. Returns itself.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/index.html b/doc/dom/event/index.html new file mode 100644 index 000000000..034e7971d --- /dev/null +++ b/doc/dom/event/index.html @@ -0,0 +1,312 @@ + + + + + Prototype v1.7_rc1 API documentation | Event + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Event +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    The namespace for Prototype's event system.

    + +
    Events: a fine mess
    + +

    Event management is one of the really sore spots of cross-browser +scripting.

    + +

    True, the prevalent issue is: everybody does it the W3C way, and MSIE +does it another way altogether. But there are quite a few subtler, +sneakier issues here and there waiting to bite your ankle — such as the +keypress/keydown issue with KHTML-based browsers (Konqueror and +Safari). Also, MSIE has a tendency to leak memory when it comes to +discarding event handlers.

    + +
    Prototype to the rescue
    + +

    Of course, Prototype smooths it over so well you'll forget these +troubles even exist. Enter the Event namespace. It is replete with +methods that help to normalize the information reported by events across +browsers.

    + +

    Event also provides a standardized list of key codes you can use with +keyboard-related events, including KEY_BACKSPACE, KEY_TAB, +KEY_RETURN, KEY_ESC, KEY_LEFT, KEY_UP, KEY_RIGHT, KEY_DOWN, +KEY_DELETE, KEY_HOME, KEY_END, KEY_PAGEUP, KEY_PAGEDOWN and +KEY_INSERT.

    + +

    The functions you're most likely to use a lot are Event.observe, +Event.element and Event.stop. If your web app uses custom events, +you'll also get a lot of mileage out of Event.fire.

    + +
    Instance methods on event objects
    + +

    As of Prototype 1.6, all methods on the Event object are now also +available as instance methods on the event object itself:

    + +

    Before

    + +
    $('foo').observe('click', respondToClick);
    + function respondToClick(event) {
    +  var element = Event.element(event);
    +  element.addClassName('active');
    +}
    +
    +
    + +

    After

    + +
    $('foo').observe('click', respondToClick);
    + function respondToClick(event) {
    +  var element = event.element();
    +  element.addClassName('active');
    +}
    +
    +
    + +

    These methods are added to the event object through Event.extend, +in the same way that Element methods are added to DOM nodes through +Element.extend. Events are extended automatically when handlers are +registered with Prototype's Event.observe method; if you're using a +different method of event registration, for whatever reason,you'll need to +extend these events manually with Event.extend.

    +
    +
    + + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Event.Handler

      + +

      Creates an observer on an element that listens for a particular event on +that element's descendants, optionally filtering by a CSS selector.

      +
    • +
    +
    +
    + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/dom/event/isleftclick/index.html b/doc/dom/event/isleftclick/index.html new file mode 100644 index 000000000..5b3d8ba0f --- /dev/null +++ b/doc/dom/event/isleftclick/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.isLeftClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.isLeftClick +

    + + + + +
    +
    +
    +
    +
    +
    Event.isLeftClick(event) → Boolean
    + + +

    Determines whether a button-related mouse event involved the left +mouse button.

    + +

    Keep in mind that the "left" mouse button is actually the "primary" mouse +button. When a mouse is in left-handed mode, the browser will report +clicks of the right button as "left-clicks."

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/ismiddleclick/index.html b/doc/dom/event/ismiddleclick/index.html new file mode 100644 index 000000000..3a9882974 --- /dev/null +++ b/doc/dom/event/ismiddleclick/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.isMiddleClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.isMiddleClick +

    + + + + +
    +
    +
    +
    +
    +
    Event.isMiddleClick(event) → Boolean
    + + +

    Determines whether a button-related mouse event involved the middle +mouse button.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/isrightclick/index.html b/doc/dom/event/isrightclick/index.html new file mode 100644 index 000000000..d61bffb39 --- /dev/null +++ b/doc/dom/event/isrightclick/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.isRightClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.isRightClick +

    + + + + +
    +
    +
    +
    +
    +
    Event.isRightClick(event) → Boolean
    + + +

    Determines whether a button-related mouse event involved the right +mouse button.

    + +

    Keep in mind that the "left" mouse button is actually the "secondary" +mouse button. When a mouse is in left-handed mode, the browser will +report clicks of the left button as "left-clicks."

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/observe/index.html b/doc/dom/event/observe/index.html new file mode 100644 index 000000000..d2737134e --- /dev/null +++ b/doc/dom/event/observe/index.html @@ -0,0 +1,338 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.observe + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.observe +

    + + + + +
    +
    +
    +
    +
    +
    Event.observe(element, eventName, handler) → Element
    +
      +
    • + element + (Element | String) + – The DOM element to observe, or its ID. +
    • +
    • + eventName + (String) + – The name of the event, in all lower case, without the "on" prefix — e.g., "click" (not "onclick"). +
    • +
    • + handler + (Function) + – The function to call when the event occurs. +
    • +
    + + +

    Registers an event handler on a DOM element. Aliased as Element#observe.

    + +

    Event.observe smooths out a variety of differences between browsers +and provides some handy additional features as well. Key features in brief:

    + +
      +
    • Several handlers can be registered for the same event on the same element.
    • +
    • Prototype figures out whether to use addEventListener (W3C standard) or +attachEvent (MSIE); you don't have to worry about it.
    • +
    • The handler is passed an extended Event object (even on MSIE).
    • +
    • The handler's context (this value) is set to the extended element +being observed (even if the event actually occurred on a descendent +element and bubbled up).
    • +
    • Prototype handles cleaning up the handler when leaving the page +(important for MSIE memory leak prevention).
    • +
    • Event.observe makes it possible to stop observing the event easily +via Event.stopObserving.
    • +
    • Adds support for mouseenter / mouseleave events in all browsers.
    • +
    + +

    Although you can use Event.observe directly and there are times when +that's the most convenient or direct way, it's more common to use its +alias Element#observe. These two statements have the same effect:

    + +
    Event.observe('foo', 'click', myHandler);
    +$('foo').observe('click', myHandler);
    +
    +
    + +

    The examples in this documentation use the Element#observe form.

    + +
    The Handler
    + +

    Signature:

    + +
    function handler(event) {
    +  // `this` = the element being observed
    +}
    +
    +
    + +

    So for example, this will turn the background of the element 'foo' blue +when it's clicked:

    + +
    $('foo').observe('click', function(event) {
    +  this.setStyle({backgroundColor: 'blue'});
    +});
    +
    +
    + +

    Note that we used this to refer to the element, and that we received the +event object as a parameter (even on MSIE).

    + +
    It's All About Timing
    + +

    One of the most common errors trying to observe events is trying to do it +before the element exists in the DOM. Don't try to observe elements until +after the dom:loaded event or window load event +has been fired.

    + +
    Preventing the Default Event Action and Bubbling
    + +

    If we want to stop the event (e.g., prevent its default action and stop it +bubbling), we can do so with the extended event object's Event#stop +method:

    + +
    $('foo').observe('click', function(event) {
    +  event.stop();
    +});
    +
    +
    + +
    Finding the Element Where the Event Occurred
    + +

    Since most events bubble from descendant elements up through the hierarchy +until they're handled, we can observe an event on a container rather than +individual elements within the container. This is sometimes called "event +delegation". It's particularly handy for tables:

    + +
    <table id='records'>
    +  <thead>
    +    <tr><th colspan='2'>No record clicked</th></tr>
    +  </thead>
    +  <tbody>
    +    <tr data-recnum='1'><td>1</td><td>First record</td></tr>
    +    <tr data-recnum='2'><td>2</td><td>Second record</td></tr>
    +    <tr data-recnum='3'><td>3</td><td>Third record</td></tr>
    +  </tbody>
    +</table>
    +
    +
    + +

    Instead of observing each cell or row, we can simply observe the table:

    + +
    $('records').observe('click', function(event) {
    +  var clickedRow = event.findElement('tr');
    +  if (clickedRow) {
    +    this.down('th').update("You clicked record #" + clickedRow.readAttribute("data-recnum"));
    +  }
    +});
    +
    +
    + +

    When any row in the table is clicked, we update the table's first header +cell saying which record was clicked. Event#findElement finds the row +that was clicked, and this refers to the table we were observing.

    + +
    Stopping Observing the Event
    + +

    If we don't need to observe the event anymore, we can stop observing it +with Event.stopObserving or its Element#stopObserving alias.

    + +
    Using an Instance Method as a Handler
    + +

    If we want to use an instance method as a handler, we will probably want +to use Function#bind to set the handler's context; otherwise, the +context will be lost and this won't mean what we expect it to mean +within the handler function. E.g.:

    + +
    var MyClass = Class.create({
    +  initialize: function(name, element) {
    +    this.name = name;
    +    element = $(element);
    +    if (element) {
    +      element.observe(this.handleClick.bind(this));
    +    }
    +  },
    +  handleClick: function(event) {
    +    alert("My name is " + this.name);
    +  },
    +});
    +
    +
    + +

    Without the Function#bind, when handleClick was triggered by the +event, this wouldn't refer to the instance and so the alert wouldn't +show the name. Because we used Function#bind, it works correctly. See +Function#bind for details. There's also Function#bindAsEventListener, +which is handy for certain very specific situations. (Normally, +Function#bind is all you need.)

    + +
    Side Notes
    + +

    Although Prototype smooths out most of the differences between browsers, +the fundamental behavior of a browser implementation isn't changed. For +example, the timing of the change or blur events varies a bit from +browser to browser.

    + +
    Changes in 1.6.x
    + +

    Prior to Prototype 1.6, Event.observe supported a fourth argument +(useCapture), a boolean that indicated whether to use the browser's +capturing phase or its bubbling phase. Since MSIE does not support the +capturing phase, we removed this argument from 1.6, lest it give users the +false impression that they can use the capturing phase in all browsers.

    + +

    1.6 also introduced setting the this context to the element being +observed, automatically extending the Event object, and the +Event#findElement method.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/on/index.html b/doc/dom/event/on/index.html new file mode 100644 index 000000000..81ada0423 --- /dev/null +++ b/doc/dom/event/on/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.on + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.on +

    + + + + +
    +
    +
    +
    +
    +
    Event.on(element, eventName, selector, callback) → Event.Handler
    + + +

    Listens for events on an element's descendants, optionally filtering +to match a given CSS selector.

    + +

    Creates an instance of Event.Handler, calls Event.Handler#start, +then returns that instance. Keep a reference to this returned instance if +you later want to unregister the observer.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/pointer/index.html b/doc/dom/event/pointer/index.html new file mode 100644 index 000000000..a6626e85b --- /dev/null +++ b/doc/dom/event/pointer/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.pointer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.pointer +

    + + + + +
    +
    +
    +
    +
    +
    Event.pointer(event) → Object
    + + +

    Returns the absolute position of the pointer for a mouse event.

    + +

    Returns an object in the form { x: Number, y: Number}.

    + +

    Note that this position is absolute on the page, not on the +viewport.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/pointerx/index.html b/doc/dom/event/pointerx/index.html new file mode 100644 index 000000000..417b2ab6e --- /dev/null +++ b/doc/dom/event/pointerx/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.pointerX + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.pointerX +

    + + + + +
    +
    +
    +
    +
    +
    Event.pointerX(event) → Number
    + + +

    Returns the absolute horizontal position of the pointer for a mouse +event.

    + +

    Note that this position is absolute on the <body>, not on the +viewport: scrolling right increases the returned value for events on +the same viewport location.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/pointery/index.html b/doc/dom/event/pointery/index.html new file mode 100644 index 000000000..0b9da40c8 --- /dev/null +++ b/doc/dom/event/pointery/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.pointerY + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.pointerY +

    + + + + +
    +
    +
    +
    +
    +
    Event.pointerY(event) → Number
    + + +

    Returns the absolute vertical position of the pointer for a mouse +event.

    + +

    Note that this position is absolute on the <body>, not on the +viewport: scrolling down increases the returned value for events on +the same viewport location.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/element/index.html b/doc/dom/event/prototype/element/index.html new file mode 100644 index 000000000..9e9110ff4 --- /dev/null +++ b/doc/dom/event/prototype/element/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#element + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Event#element +

    + + + + +
    +
    +
    +
    +
    +
    Event#element() → Element
    +
      +
    • + event + (Event) + – An Event object +
    • +
    + + +

    Returns the DOM element on which the event occurred. This method +is deprecated, use Event.findElement instead.

    + +
    Example
    + +

    Here's a simple bit of code which hides any paragraph when directly clicked.

    + +
    document.observe('click', function(event) {
    +  var element = Event.element(event);
    +  if ('P' == element.tagName)
    +    element.hide();
    +});
    +
    +
    + +
    See also
    + +

    There is a subtle distinction between this function and +Event.findElement.

    + +
    Note for Prototype 1.5.0
    + +

    Note that prior to version 1.5.1, if the browser does not support +native DOM extensions (see the Element section for further details), +the element returned by Event.element might very well +not be extended. If you intend to use methods from Element.Methods +on it, you need to wrap the call in the $ function like so:

    + +
    document.observe('click', function(event) {
    +  var element = $(Event.element(event));
    +  // ...
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/extend/index.html b/doc/dom/event/prototype/extend/index.html new file mode 100644 index 000000000..410818594 --- /dev/null +++ b/doc/dom/event/prototype/extend/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#extend +

    + + + + +
    +
    +
    +
    +
    +
    Event#extend() → Event
    + + +

    Extends event with all of the methods contained in Event.Methods.

    + +

    Note that all events inside handlers that were registered using +Event.observe or Element.observe will be extended automatically.

    + +

    You need only call Event.extend manually if you register a handler a +different way (e.g., the onclick attribute). We really can't encourage +that sort of thing, though.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/findelement/index.html b/doc/dom/event/prototype/findelement/index.html new file mode 100644 index 000000000..fd9884a17 --- /dev/null +++ b/doc/dom/event/prototype/findelement/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#findElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#findElement +

    + + + + +
    +
    +
    +
    +
    +
    Event#findElement([expression]) → Element
    +
      +
    • + event + (Event) + – An Event object +
    • +
    • + expression + (String) + – An optional CSS selector +
    • +
    + + +

    Returns the first DOM element that matches a given CSS selector — +starting with the element on which the event occurred, then moving up +its ancestor chain. If expression is not given, the element which fired +the event is returned.

    + +

    *If no matching element is found, the document itself (HTMLDocument node) +is returned.*

    + +
    Example
    + +

    Here's a simple code that lets you click everywhere on the page and hides +the closest-fitting paragraph around your click (if any).

    + +
    document.observe('click', function(event) {
    +  var element = Event.findElement(event, 'p');
    +  if (element != document)
    +    $(element).hide();
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/isleftclick/index.html b/doc/dom/event/prototype/isleftclick/index.html new file mode 100644 index 000000000..9c6abd07c --- /dev/null +++ b/doc/dom/event/prototype/isleftclick/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#isLeftClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#isLeftClick +

    + + + + +
    +
    +
    +
    +
    +
    Event#isLeftClick() → Boolean
    + + +

    Determines whether a button-related mouse event involved the left +mouse button.

    + +

    Keep in mind that the "left" mouse button is actually the "primary" mouse +button. When a mouse is in left-handed mode, the browser will report +clicks of the right button as "left-clicks."

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/ismiddleclick/index.html b/doc/dom/event/prototype/ismiddleclick/index.html new file mode 100644 index 000000000..c55de5769 --- /dev/null +++ b/doc/dom/event/prototype/ismiddleclick/index.html @@ -0,0 +1,167 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#isMiddleClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#isMiddleClick +

    + + + + +
    +
    +
    +
    +
    +
    Event#isMiddleClick() → Boolean
    + + +

    Determines whether a button-related mouse event involved the middle +mouse button.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/isrightclick/index.html b/doc/dom/event/prototype/isrightclick/index.html new file mode 100644 index 000000000..54815ef34 --- /dev/null +++ b/doc/dom/event/prototype/isrightclick/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#isRightClick + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#isRightClick +

    + + + + +
    +
    +
    +
    +
    +
    Event#isRightClick() → Boolean
    + + +

    Determines whether a button-related mouse event involved the right +mouse button.

    + +

    Keep in mind that the "left" mouse button is actually the "secondary" +mouse button. When a mouse is in left-handed mode, the browser will +report clicks of the left button as "left-clicks."

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/pointer/index.html b/doc/dom/event/prototype/pointer/index.html new file mode 100644 index 000000000..6fc653128 --- /dev/null +++ b/doc/dom/event/prototype/pointer/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#pointer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#pointer +

    + + + + +
    +
    +
    +
    +
    +
    Event#pointer() → Object
    + + +

    Returns the absolute position of the pointer for a mouse event.

    + +

    Returns an object in the form { x: Number, y: Number}.

    + +

    Note that this position is absolute on the page, not on the +viewport.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/pointerx/index.html b/doc/dom/event/prototype/pointerx/index.html new file mode 100644 index 000000000..9ce07d7aa --- /dev/null +++ b/doc/dom/event/prototype/pointerx/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#pointerX + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#pointerX +

    + + + + +
    +
    +
    +
    +
    +
    Event#pointerX() → Number
    + + +

    Returns the absolute horizontal position of the pointer for a mouse +event.

    + +

    Note that this position is absolute on the <body>, not on the +viewport: scrolling right increases the returned value for events on +the same viewport location.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/pointery/index.html b/doc/dom/event/prototype/pointery/index.html new file mode 100644 index 000000000..bd4b3cfa7 --- /dev/null +++ b/doc/dom/event/prototype/pointery/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#pointerY + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#pointerY +

    + + + + +
    +
    +
    +
    +
    +
    Event#pointerY() → Number
    + + +

    Returns the absolute vertical position of the pointer for a mouse +event.

    + +

    Note that this position is absolute on the <body>, not on the +viewport: scrolling down increases the returned value for events on +the same viewport location.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/prototype/stop/index.html b/doc/dom/event/prototype/stop/index.html new file mode 100644 index 000000000..8a3daa558 --- /dev/null +++ b/doc/dom/event/prototype/stop/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Event#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Event#stop +

    + + + + +
    +
    +
    +
    +
    +
    Event#stop() → undefined
    + + +

    Stops the event's propagation and prevents its eventual default action +from being triggered.

    + +

    Stopping an event also sets a stopped property on that event for +future inspection.

    + +

    There are two aspects to how your browser handles an event once it fires up:

    + +
      +
    1. The browser usually triggers event handlers on the actual element the +event occurred on, then on its parent element, and so on and so forth, +until the document's root element is reached. This is called +event bubbling, and is the most common form of event propagation. You +may very well want to stop this propagation when you just handled an event, +and don't want it to keep bubbling up (or see no need for it).

    2. +
    3. Once your code had a chance to process the event, the browser handles +it as well, if that event has a default behavior. For instance, clicking +on links navigates to them; submitting forms sends them over to the server +side; hitting the Return key in a single-line form field submits it; etc. +You may very well want to prevent this default behavior if you do your own +handling.

    4. +
    + +

    Because stopping one of those aspects means, in 99.9% of the cases, +preventing the other one as well, Prototype bundles both in this stop +function. Calling it on an event object, stops propagation and prevents +the default behavior.

    + +
    Example
    + +

    Here's a simple script that prevents a form from being sent to the server +side if certain field is empty.

    + +
    Event.observe('signinForm', 'submit', function(event) {
    +  var login = $F('login').strip();
    +  if ('' == login) {
    +    Event.stop(event);
    +    // Display the issue one way or another
    +  }
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/stop/index.html b/doc/dom/event/stop/index.html new file mode 100644 index 000000000..dc6a73608 --- /dev/null +++ b/doc/dom/event/stop/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.stop +

    + + + + +
    +
    +
    +
    +
    +
    Event.stop(event) → undefined
    + + +

    Stops the event's propagation and prevents its eventual default action +from being triggered.

    + +

    Stopping an event also sets a stopped property on that event for +future inspection.

    + +

    There are two aspects to how your browser handles an event once it fires up:

    + +
      +
    1. The browser usually triggers event handlers on the actual element the +event occurred on, then on its parent element, and so on and so forth, +until the document's root element is reached. This is called +event bubbling, and is the most common form of event propagation. You +may very well want to stop this propagation when you just handled an event, +and don't want it to keep bubbling up (or see no need for it).

    2. +
    3. Once your code had a chance to process the event, the browser handles +it as well, if that event has a default behavior. For instance, clicking +on links navigates to them; submitting forms sends them over to the server +side; hitting the Return key in a single-line form field submits it; etc. +You may very well want to prevent this default behavior if you do your own +handling.

    4. +
    + +

    Because stopping one of those aspects means, in 99.9% of the cases, +preventing the other one as well, Prototype bundles both in this stop +function. Calling it on an event object, stops propagation and prevents +the default behavior.

    + +
    Example
    + +

    Here's a simple script that prevents a form from being sent to the server +side if certain field is empty.

    + +
    Event.observe('signinForm', 'submit', function(event) {
    +  var login = $F('login').strip();
    +  if ('' == login) {
    +    Event.stop(event);
    +    // Display the issue one way or another
    +  }
    +});
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/event/stopobserving/index.html b/doc/dom/event/stopobserving/index.html new file mode 100644 index 000000000..fa27559c2 --- /dev/null +++ b/doc/dom/event/stopobserving/index.html @@ -0,0 +1,247 @@ + + + + + Prototype v1.7_rc1 API documentation | Event.stopObserving + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Event.stopObserving +

    + + + + +
    +
    +
    +
    +
    +
    Event.stopObserving(element[, eventName[, handler]]) → Element
    +
      +
    • + element + (Element | String) + – The element to stop observing, or its ID. +
    • +
    • + eventName + (String) + – (Optional) The name of the event to stop observing, in all lower case, without the "on" — e.g., "click" (not "onclick"). +
    • +
    • + handler + (Function) + – (Optional) The handler to remove; must be the exact same reference that was passed to Event.observe. +
    • +
    + + +

    Unregisters one or more event handlers.

    + +

    If handler is omitted, unregisters all event handlers on element +for that eventName. If eventName is also omitted, unregisters all +event handlers on element. (In each case, only affects handlers +registered via Prototype.)

    + +
    Examples
    + +

    Assuming:

    + +
    $('foo').observe('click', myHandler);
    +
    +
    + +

    ...we can stop observing using that handler like so:

    + +
    $('foo').stopObserving('click', myHandler);
    +
    +
    + +

    If we want to remove all 'click' handlers from 'foo', we leave off the +handler argument:

    + +
    $('foo').stopObserving('click');
    +
    +
    + +

    If we want to remove all handlers for all events from 'foo' (perhaps +we're about to remove it from the DOM), we simply omit both the handler +and the event name:

    + +
    $('foo').stopObserving();
    +
    +
    + +
    A Common Error
    + +

    When using instance methods as observers, it's common to use +Function#bind on them, e.g.:

    + +
    $('foo').observe('click', this.handlerMethod.bind(this));
    +
    +
    + +

    If you do that, this will not work to unregister the handler:

    + +
    $('foo').stopObserving('click', this.handlerMethod.bind(this)); // <== WRONG
    +
    +
    + +

    Function#bind returns a new function every time it's called, and so +if you don't retain the reference you used when observing, you can't +unhook that function specifically. (You can still unhook all handlers +for an event, or all handlers on the element entirely.)

    + +

    To do this, you need to keep a reference to the bound function:

    + +
    this.boundHandlerMethod = this.handlerMethod.bind(this);
    +$('foo').observe('click', this.boundHandlerMethod);
    +
    +
    + +

    ...and then to remove:

    + +
    $('foo').stopObserving('click', this.boundHandlerMethod); // <== Right
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/disable/index.html b/doc/dom/form/disable/index.html new file mode 100644 index 000000000..a2a794f9f --- /dev/null +++ b/doc/dom/form/disable/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.disable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.disable +

    + + + + +
    +
    +
    +
    +
    +
    Form.disable(form) → Element
    + + +

    Disables the form as a whole. Form controls will be visible but +uneditable.

    + +

    Disabling the form is done by iterating over form elements and calling +Form.Element.disable on them.

    + +
    Note
    + +

    Keep in mind that disabled elements are skipped by serialization +methods! You cannot serialize a disabled form.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/activate/index.html b/doc/dom/form/element/activate/index.html new file mode 100644 index 000000000..9b505411f --- /dev/null +++ b/doc/dom/form/element/activate/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.activate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.activate +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.activate(element) → Element
    + + +

    Gives focus to a form control and selects its contents if it is a text +input.

    + +

    This method is just a shortcut for focusing and selecting; therefore, +these are equivalent (aside from the fact that the former one will not +return the field) :

    + +
    Form.Element.focus('myelement').select()
    +$('myelement').activate()
    +
    +
    + +

    Guess which call is the nicest? ;)

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/clear/index.html b/doc/dom/form/element/clear/index.html new file mode 100644 index 000000000..15dcd68a3 --- /dev/null +++ b/doc/dom/form/element/clear/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.clear + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.clear +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.clear(element) → Element
    + + +

    Clears the contents of a text input. Returns the element.

    + +
    Example
    + +

    This code sets up a text field in a way that it clears its contents the +first time it receives focus:

    + +
      $('some_field').onfocus = function() {
    +    // if already cleared, do nothing
    +    if (this._cleared) return
    +     // when this code is executed, "this" keyword will in fact be the field itself
    +    this.clear()
    +    this._cleared = true
    +  }
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/disable/index.html b/doc/dom/form/element/disable/index.html new file mode 100644 index 000000000..7fe2713c0 --- /dev/null +++ b/doc/dom/form/element/disable/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.disable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.disable +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.disable(element) → Element
    + + +

    Disables a form control, effectively preventing its value from changing +until it is enabled again.

    + +

    This method sets the native disabled property of an element to true. +You can use this property to check the state of a control.

    + +
    Notes
    + +

    Disabled form controls are never serialized.

    + +

    Never disable a form control as a security measure without having +validation for it server-side. A user with minimal experience of +JavaScript can enable these fields on your site easily using any browser. +Instead, use disabling as a usability enhancement - with it you can +indicate that a specific value should not be changed at the time being.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/enable/index.html b/doc/dom/form/element/enable/index.html new file mode 100644 index 000000000..2c7c84977 --- /dev/null +++ b/doc/dom/form/element/enable/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.enable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.enable +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.enable(element) → Element
    + + +

    Enables a previously disabled form control.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/eventobserver/index.html b/doc/dom/form/element/eventobserver/index.html new file mode 100644 index 000000000..a9aa2693a --- /dev/null +++ b/doc/dom/form/element/eventobserver/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.EventObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Form.Element.EventObserver +

    + + + + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/dom/form/element/focus/index.html b/doc/dom/form/element/focus/index.html new file mode 100644 index 000000000..3a8a37fa4 --- /dev/null +++ b/doc/dom/form/element/focus/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.focus + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.focus +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.focus(element) → Element
    + + +

    Gives keyboard focus to an element. Returns the element.

    + +
    Example
    + +
    Form.Element.focus('searchbox')
    + // Almost equivalent, but does NOT return the form element (uses the native focus() method):
    +$('searchbox').focus()
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/getvalue/index.html b/doc/dom/form/element/getvalue/index.html new file mode 100644 index 000000000..9488344c0 --- /dev/null +++ b/doc/dom/form/element/getvalue/index.html @@ -0,0 +1,192 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.getValue + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.getValue +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.getValue(element) → String | Array
    + + +

    Returns the current value of a form control.

    + +

    A string is returned for most controls; only multiple select boxes +return an array of values.

    + +

    The global shortcut for this method is $F.

    + +
    How to reference form controls by their name
    + +

    This method is consistent with other DOM extensions in that it requires an +element *ID* as the string argument, not the name of the +form control (as some might think). If you want to reference controls by +their names, first find the control the regular JavaScript way and use the +node itself instead of an ID as the argument.

    + +

    For example, if you have an input named "company" in a form with an +ID "contact":

    + +
    var form = $('contact');
    +var input = form['company'];
    + Form.Element.getValue(input);
    + // but, the preferred call is:
    +$(input).getValue(); // we used the $() method so the node gets extended
    + // you can also use the shortcut
    +$F(input);
    +
    +
    + +
    Note
    + +

    An error is thrown ("element has no properties") if the element argument +is an unknown ID.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/index.html b/doc/dom/form/element/index.html new file mode 100644 index 000000000..60e8a9510 --- /dev/null +++ b/doc/dom/form/element/index.html @@ -0,0 +1,275 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Form.Element +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Utilities for dealing with form controls in the DOM.

    + +

    This is a collection of methods that assist in dealing with form controls. +They provide ways to focus, serialize, disable/enable +or extract current value from a specific control.

    + +

    Note that nearly all these methods are available directly on input, +select, and textarea elements. Therefore, these are equivalent:

    + +
    Form.Element.activate('myfield');
    +$('myfield').activate();
    +
    +
    + +

    Naturally, you should always prefer the shortest form suitable in a +situation. Most of these methods also return the element itself (as +indicated by the return type) for chainability.

    +
    +
    + + + +
    +
    +

    Classes

    +
    +
    + + +
    +
    + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/dom/form/element/observer/index.html b/doc/dom/form/element/observer/index.html new file mode 100644 index 000000000..9f81b139b --- /dev/null +++ b/doc/dom/form/element/observer/index.html @@ -0,0 +1,178 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.Observer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Form.Element.Observer +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    An Abstract.TimedObserver subclass that watches for changes to a form +field's value. This triggers the callback when the form field's value +(according to Form.Element.getValue) changes. (Note that when the value +actually changes can vary from browser to browser, particularly with +select boxes.)

    + +

    Form.Element observer implements the getValue() method using +Form.Element.getValue on the given element. See Abstract.TimedObserver +for general documentation on timed observers.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + + +
    + + + +
    + + diff --git a/doc/dom/form/element/observer/new/index.html b/doc/dom/form/element/observer/new/index.html new file mode 100644 index 000000000..18bad53a5 --- /dev/null +++ b/doc/dom/form/element/observer/new/index.html @@ -0,0 +1,159 @@ + + + + + Prototype v1.7_rc1 API documentation | new Form.Element.Observer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Form.Element.Observer +

    + + + + +
    +
    +
    +
    +
    +
    new(element, frequency, callback)
    +
      +
    • + element + (String | Element) + – The form element to watch. Can be an element instance or an ID. +
    • +
    • + frequency + (Number) + – The frequency, in seconds — e.g., 0.33 to check for changes every third of a second. +
    • +
    • + callback + (Function) + – The callback to trigger when the value changes. +
    • +
    + + +

    Creates a Form.Element.Observer.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/present/index.html b/doc/dom/form/element/present/index.html new file mode 100644 index 000000000..2a7e77cfc --- /dev/null +++ b/doc/dom/form/element/present/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.present + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.present +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.present(element) → Element
    + + +

    Returns true if a text input has contents, false otherwise.

    + +
    Example
    + +

    This method is very handy in a generic form validation routine. +On the following form's submit event, the presence of each text input is +checked and lets the user know if they left a text input blank.

    + +
    <form id="example" class="example" action="#">
    +  <fieldset>
    +    <legend>User Details</legend>
    +    <p id="msg" class="message">Please fill out the following fields:</p>
    +    <p>
    +      <label for="username">Username</label>
    +      <input id="username" type="text" name="username" />
    +    </p>
    +    <p>
    +      <label for="email">Email Address</label>
    +      <input id="email" type="text" name="email" />
    +    </p>
    +    <input type="submit" value="submit" />
    +  </fieldset>
    +</form>
    + <script type="text/javascript">
    +  $('example').onsubmit = function(){
    +    var valid, msg = $('msg')
    +     // are both fields present?
    +    valid = $(this.username).present() && $(this.email).present()
    +     if (valid) {
    +      // in the real world we would return true here to allow the form to be submitted
    +      // return true
    +      msg.update('Passed validation!').style.color = 'green'
    +    } else {
    +      msg.update('Please fill out <em>all</em> the fields.').style.color = 'red'
    +    }
    +    return false
    +  }
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/prototype/activate/index.html b/doc/dom/form/element/prototype/activate/index.html new file mode 100644 index 000000000..490d77604 --- /dev/null +++ b/doc/dom/form/element/prototype/activate/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#activate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#activate +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#activate() → Element
    + + +

    Gives focus to a form control and selects its contents if it is a text +input.

    + +

    This method is just a shortcut for focusing and selecting; therefore, +these are equivalent (aside from the fact that the former one will not +return the field) :

    + +
    Form.Element.focus('myelement').select()
    +$('myelement').activate()
    +
    +
    + +

    Guess which call is the nicest? ;)

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/prototype/clear/index.html b/doc/dom/form/element/prototype/clear/index.html new file mode 100644 index 000000000..a20a3e255 --- /dev/null +++ b/doc/dom/form/element/prototype/clear/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#clear + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#clear +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#clear() → Element
    + + +

    Clears the contents of a text input. Returns the element.

    + +
    Example
    + +

    This code sets up a text field in a way that it clears its contents the +first time it receives focus:

    + +
      $('some_field').onfocus = function() {
    +    // if already cleared, do nothing
    +    if (this._cleared) return
    +     // when this code is executed, "this" keyword will in fact be the field itself
    +    this.clear()
    +    this._cleared = true
    +  }
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/prototype/disable/index.html b/doc/dom/form/element/prototype/disable/index.html new file mode 100644 index 000000000..fad732f1b --- /dev/null +++ b/doc/dom/form/element/prototype/disable/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#disable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#disable +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#disable() → Element
    + + +

    Disables a form control, effectively preventing its value from changing +until it is enabled again.

    + +

    This method sets the native disabled property of an element to true. +You can use this property to check the state of a control.

    + +
    Notes
    + +

    Disabled form controls are never serialized.

    + +

    Never disable a form control as a security measure without having +validation for it server-side. A user with minimal experience of +JavaScript can enable these fields on your site easily using any browser. +Instead, use disabling as a usability enhancement - with it you can +indicate that a specific value should not be changed at the time being.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/prototype/enable/index.html b/doc/dom/form/element/prototype/enable/index.html new file mode 100644 index 000000000..43230b981 --- /dev/null +++ b/doc/dom/form/element/prototype/enable/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#enable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#enable +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#enable() → Element
    + + +

    Enables a previously disabled form control.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/prototype/getvalue/index.html b/doc/dom/form/element/prototype/getvalue/index.html new file mode 100644 index 000000000..4110d4b39 --- /dev/null +++ b/doc/dom/form/element/prototype/getvalue/index.html @@ -0,0 +1,192 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#getValue + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#getValue +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#getValue() → String | Array
    + + +

    Returns the current value of a form control.

    + +

    A string is returned for most controls; only multiple select boxes +return an array of values.

    + +

    The global shortcut for this method is $F.

    + +
    How to reference form controls by their name
    + +

    This method is consistent with other DOM extensions in that it requires an +element *ID* as the string argument, not the name of the +form control (as some might think). If you want to reference controls by +their names, first find the control the regular JavaScript way and use the +node itself instead of an ID as the argument.

    + +

    For example, if you have an input named "company" in a form with an +ID "contact":

    + +
    var form = $('contact');
    +var input = form['company'];
    + Form.Element.getValue(input);
    + // but, the preferred call is:
    +$(input).getValue(); // we used the $() method so the node gets extended
    + // you can also use the shortcut
    +$F(input);
    +
    +
    + +
    Note
    + +

    An error is thrown ("element has no properties") if the element argument +is an unknown ID.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/prototype/present/index.html b/doc/dom/form/element/prototype/present/index.html new file mode 100644 index 000000000..8abc8a709 --- /dev/null +++ b/doc/dom/form/element/prototype/present/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#present + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#present +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#present() → Element
    + + +

    Returns true if a text input has contents, false otherwise.

    + +
    Example
    + +

    This method is very handy in a generic form validation routine. +On the following form's submit event, the presence of each text input is +checked and lets the user know if they left a text input blank.

    + +
    <form id="example" class="example" action="#">
    +  <fieldset>
    +    <legend>User Details</legend>
    +    <p id="msg" class="message">Please fill out the following fields:</p>
    +    <p>
    +      <label for="username">Username</label>
    +      <input id="username" type="text" name="username" />
    +    </p>
    +    <p>
    +      <label for="email">Email Address</label>
    +      <input id="email" type="text" name="email" />
    +    </p>
    +    <input type="submit" value="submit" />
    +  </fieldset>
    +</form>
    + <script type="text/javascript">
    +  $('example').onsubmit = function(){
    +    var valid, msg = $('msg')
    +     // are both fields present?
    +    valid = $(this.username).present() && $(this.email).present()
    +     if (valid) {
    +      // in the real world we would return true here to allow the form to be submitted
    +      // return true
    +      msg.update('Passed validation!').style.color = 'green'
    +    } else {
    +      msg.update('Please fill out <em>all</em> the fields.').style.color = 'red'
    +    }
    +    return false
    +  }
    +</script>
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/prototype/serialize/index.html b/doc/dom/form/element/prototype/serialize/index.html new file mode 100644 index 000000000..d1dbe9fbf --- /dev/null +++ b/doc/dom/form/element/prototype/serialize/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#serialize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#serialize +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#serialize() → String
    + + +

    Returns a URL-encoded string representation of a form control in the +name=value format.

    + +

    The result of this method is a string suitable for Ajax requests. However, +it serializes only a single element - if you need to serialize the whole +form use Form.serialize instead.

    + +
    Notes
    + +

    Serializing a disabled control or a one without a name will always result +in an empty string.

    + +

    If you simply need an element's value for reasons other than Ajax +requests, use Form.Element.getValue instead.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/prototype/setvalue/index.html b/doc/dom/form/element/prototype/setvalue/index.html new file mode 100644 index 000000000..14dd2939d --- /dev/null +++ b/doc/dom/form/element/prototype/setvalue/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element#setValue + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form.Element#setValue +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element#setValue(value) → Element
    + + +

    Sets value to be the value of the form control. Returns the element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/select/index.html b/doc/dom/form/element/select/index.html new file mode 100644 index 000000000..64120e433 --- /dev/null +++ b/doc/dom/form/element/select/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.select +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.select(element) → Element
    + + +

    Selects the current text in a text input. Returns the element.

    + +
    Example
    + +

    Some search boxes are set up so that they auto-select their content when they receive focus.

    + +
      $('searchbox').onfocus = function() {
    +    Form.Element.select(this)
    +     // You can also rely on the native method, but this will NOT return the element!
    +    this.select()
    +  }
    +
    +
    + +
    Focusing + selecting: use Form.Element.activate!
    + +

    The Form.Element.activate method is a nifty way to both focus a form +field and select its current text, all in one portable JavaScript call.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/serialize/index.html b/doc/dom/form/element/serialize/index.html new file mode 100644 index 000000000..1c521facc --- /dev/null +++ b/doc/dom/form/element/serialize/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.serialize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.serialize +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.serialize(element) → String
    + + +

    Returns a URL-encoded string representation of a form control in the +name=value format.

    + +

    The result of this method is a string suitable for Ajax requests. However, +it serializes only a single element - if you need to serialize the whole +form use Form.serialize instead.

    + +
    Notes
    + +

    Serializing a disabled control or a one without a name will always result +in an empty string.

    + +

    If you simply need an element's value for reasons other than Ajax +requests, use Form.Element.getValue instead.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/element/setvalue/index.html b/doc/dom/form/element/setvalue/index.html new file mode 100644 index 000000000..7ff6a15c5 --- /dev/null +++ b/doc/dom/form/element/setvalue/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Element.setValue + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.Element.setValue +

    + + + + +
    +
    +
    +
    +
    +
    Form.Element.setValue(element, value) → Element
    + + +

    Sets value to be the value of the form control. Returns the element.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/enable/index.html b/doc/dom/form/enable/index.html new file mode 100644 index 000000000..c7afaf6b0 --- /dev/null +++ b/doc/dom/form/enable/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.enable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.enable +

    + + + + +
    +
    +
    +
    +
    +
    Form.enable(form) → Element
    + + +

    Enables a fully- or partially-disabled form.

    + +

    Enabling the form is done by iterating over form elements and calling +Form.Element.enable on them.

    + +
    Note
    + +

    This will enable all form controls regardless of how they were disabled +(by scripting or by HTML attributes).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/eventobserver/index.html b/doc/dom/form/eventobserver/index.html new file mode 100644 index 000000000..c414f9683 --- /dev/null +++ b/doc/dom/form/eventobserver/index.html @@ -0,0 +1,150 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.EventObserver + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Form.EventObserver +

    + + + + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/dom/form/findfirstelement/index.html b/doc/dom/form/findfirstelement/index.html new file mode 100644 index 000000000..0b230ea35 --- /dev/null +++ b/doc/dom/form/findfirstelement/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.findFirstElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.findFirstElement +

    + + + + +
    +
    +
    +
    +
    +
    Form.findFirstElement(form) → Element
    + + +

    Finds the first non-hidden, non-disabled control within the form.

    + +

    The returned object is either an INPUT, SELECT or TEXTAREA element. This +method is used by the Form.focusFirstElement method.

    + +
    Note
    + +

    The result of this method is the element that comes first in the +document order, not the +tabindex order.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/focusfirstelement/index.html b/doc/dom/form/focusfirstelement/index.html new file mode 100644 index 000000000..c4ecbde74 --- /dev/null +++ b/doc/dom/form/focusfirstelement/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.focusFirstElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.focusFirstElement +

    + + + + +
    +
    +
    +
    +
    +
    Form.focusFirstElement(form) → Element
    + + +

    Gives keyboard focus to the first element of the form. Returns the form.

    + +

    Uses Form.findFirstElement to get the first element and calls +Form.Element.activate on it. This is useful for enhancing usability on +your site by bringing focus on page load to forms such as search forms or +contact forms where a user is ready to start typing right away.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/getelements/index.html b/doc/dom/form/getelements/index.html new file mode 100644 index 000000000..6427fc892 --- /dev/null +++ b/doc/dom/form/getelements/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.getElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.getElements +

    + + + + +
    +
    +
    +
    +
    +
    Form.getElements(form) → [Element…]
    + + +

    Returns a collection of all controls within a form.

    + +
    Note
    + +

    OPTION elements are not included in the result; only their parent +SELECT control is.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/getinputs/index.html b/doc/dom/form/getinputs/index.html new file mode 100644 index 000000000..424b9d6e4 --- /dev/null +++ b/doc/dom/form/getinputs/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.getInputs + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.getInputs +

    + + + + +
    +
    +
    +
    +
    +
    Form.getInputs(form [, type [, name]]) → [Element…]
    +
      +
    • + type + (String) + – A value for the type attribute against which to filter. +
    • +
    • + name + (String) + – A value for the name attribute against which to filter. +
    • +
    + + +

    Returns a collection of all INPUT elements in a form.

    + +

    Use optional type and name arguments to restrict the search on +these attributes.

    + +
    Example
    + +
    var form = $('myform');
    + form.getInputs();       // -> all INPUT elements
    +form.getInputs('text'); // -> only text inputs
    + var buttons = form.getInputs('radio', 'education');
    +// -> only radio buttons of name "education"
    + // now disable these radio buttons:
    +buttons.invoke('disable');
    +
    +
    + +
    Note
    + +

    Elements are returned in the document order, not the +tabindex order.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/index.html b/doc/dom/form/index.html new file mode 100644 index 000000000..0aee03a11 --- /dev/null +++ b/doc/dom/form/index.html @@ -0,0 +1,265 @@ + + + + + Prototype v1.7_rc1 API documentation | Form + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Form +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Utilities for dealing with forms in the DOM.

    + +

    Form is a namespace for all things form-related, packed with form +manipulation and serialization goodness. While it holds methods dealing +with forms as a whole, its submodule Form.Element deals with specific +form controls.

    + +

    Many of these methods are also available directly on form elements.

    +
    +
    + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Form.Element

      + +

      Utilities for dealing with form controls in the DOM.

      +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Form.EventObserver

      + +
    • +
    • +

      Form.Observer

      + +

      An Abstract.TimedObserver subclass that watches for changes to a form. +The callback is triggered when the form changes — e.g., when any +of its fields' values changes, when fields are added/removed, etc.; anything +that affects the serialized form of the form (see Form#serialize).

      +
    • +
    +
    +
    + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/dom/form/observer/index.html b/doc/dom/form/observer/index.html new file mode 100644 index 000000000..e0fe2a3f4 --- /dev/null +++ b/doc/dom/form/observer/index.html @@ -0,0 +1,213 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.Observer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Form.Observer +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    An Abstract.TimedObserver subclass that watches for changes to a form. +The callback is triggered when the form changes — e.g., when any +of its fields' values changes, when fields are added/removed, etc.; anything +that affects the serialized form of the form (see Form#serialize).

    + +
    Example
    + +

    In this example an observer is used to change the appearance of the form +if any of the values had been changed. It returns to its initial state when +the data is submitted (saved).

    + +
    <form id="example" action="#">
    +  <fieldset>
    +    <legend>Login Preferences</legend>
    +    <p id="msg" class="message">Current settings:</p>
    +    <p>
    +      <label for="greeting">Greeting message</label>
    +      <input id="greeting" type="text" name="greeting" value="Hello world!" />
    +    </p>
    +    <h4>Login options</h4>
    +    <p>
    +        <input id="login-visible" type="checkbox" name="login-visible" checked="checked" />
    +        <label for="login-visible">allow others to see my last login date</label>
    +    </p>
    +    <p>
    +        <input id="land-recent" type="checkbox" name="land-recent" />
    +        <label for="land-recent">land on recent changes overview instead of the Dashboard</label>
    +    </p>
    +    <input type="submit" value="save" />
    +  </fieldset>
    +</form>
    + <script type="text/javascript">
    +  new Form.Observer('example', 0.3, function(form, value){
    +    $('msg').update('Your preferences have changed. Resubmit to save').style.color = 'red'
    +    form.down().setStyle({ background:'lemonchiffon', borderColor:'red' })
    +  })
    +   $('example').onsubmit = function() {
    +    $('msg').update('Preferences saved!').style.color = 'green'
    +    this.down().setStyle({ background:null, borderColor:null })
    +    return false
    +  }
    +</script>
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + + +
    + + + +
    + + diff --git a/doc/dom/form/observer/new/index.html b/doc/dom/form/observer/new/index.html new file mode 100644 index 000000000..8c02bc0a7 --- /dev/null +++ b/doc/dom/form/observer/new/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.7_rc1 API documentation | new Form.Observer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Form.Observer +

    + + + + +
    +
    +
    +
    +
    +
    new(element, frequency, callback)
    +
      +
    • + element + (String | Element) + – The element of the form to watch. Can be an element instance or an ID. +
    • +
    • + frequency + (Number) + – The frequency, in seconds -- e.g., 0.33 to check for changes every third of a second. +
    • +
    • + callback + (Function) + – The callback to trigger when the form changes. +
    • +
    + + +

    Creates a Form.Observer.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/disable/index.html b/doc/dom/form/prototype/disable/index.html new file mode 100644 index 000000000..4cddb0b2e --- /dev/null +++ b/doc/dom/form/prototype/disable/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#disable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#disable +

    + + + + +
    +
    +
    +
    +
    +
    Form#disable() → Element
    + + +

    Disables the form as a whole. Form controls will be visible but +uneditable.

    + +

    Disabling the form is done by iterating over form elements and calling +Form.Element.disable on them.

    + +
    Note
    + +

    Keep in mind that disabled elements are skipped by serialization +methods! You cannot serialize a disabled form.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/enable/index.html b/doc/dom/form/prototype/enable/index.html new file mode 100644 index 000000000..bc16b034a --- /dev/null +++ b/doc/dom/form/prototype/enable/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#enable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#enable +

    + + + + +
    +
    +
    +
    +
    +
    Form#enable() → Element
    + + +

    Enables a fully- or partially-disabled form.

    + +

    Enabling the form is done by iterating over form elements and calling +Form.Element.enable on them.

    + +
    Note
    + +

    This will enable all form controls regardless of how they were disabled +(by scripting or by HTML attributes).

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/findfirstelement/index.html b/doc/dom/form/prototype/findfirstelement/index.html new file mode 100644 index 000000000..34fdc1477 --- /dev/null +++ b/doc/dom/form/prototype/findfirstelement/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#findFirstElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#findFirstElement +

    + + + + +
    +
    +
    +
    +
    +
    Form#findFirstElement() → Element
    + + +

    Finds the first non-hidden, non-disabled control within the form.

    + +

    The returned object is either an INPUT, SELECT or TEXTAREA element. This +method is used by the Form.focusFirstElement method.

    + +
    Note
    + +

    The result of this method is the element that comes first in the +document order, not the +tabindex order.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/focusfirstelement/index.html b/doc/dom/form/prototype/focusfirstelement/index.html new file mode 100644 index 000000000..4eb30ff77 --- /dev/null +++ b/doc/dom/form/prototype/focusfirstelement/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#focusFirstElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#focusFirstElement +

    + + + + +
    +
    +
    +
    +
    +
    Form#focusFirstElement() → Element
    + + +

    Gives keyboard focus to the first element of the form. Returns the form.

    + +

    Uses Form.findFirstElement to get the first element and calls +Form.Element.activate on it. This is useful for enhancing usability on +your site by bringing focus on page load to forms such as search forms or +contact forms where a user is ready to start typing right away.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/getelements/index.html b/doc/dom/form/prototype/getelements/index.html new file mode 100644 index 000000000..780ec82cf --- /dev/null +++ b/doc/dom/form/prototype/getelements/index.html @@ -0,0 +1,166 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#getElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#getElements +

    + + + + +
    +
    +
    +
    +
    +
    Form#getElements() → [Element…]
    + + +

    Returns a collection of all controls within a form.

    + +
    Note
    + +

    OPTION elements are not included in the result; only their parent +SELECT control is.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/getinputs/index.html b/doc/dom/form/prototype/getinputs/index.html new file mode 100644 index 000000000..ee50d66ca --- /dev/null +++ b/doc/dom/form/prototype/getinputs/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#getInputs + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#getInputs +

    + + + + +
    +
    +
    +
    +
    +
    Form#getInputs([type [, name]]) → [Element…]
    +
      +
    • + type + (String) + – A value for the type attribute against which to filter. +
    • +
    • + name + (String) + – A value for the name attribute against which to filter. +
    • +
    + + +

    Returns a collection of all INPUT elements in a form.

    + +

    Use optional type and name arguments to restrict the search on +these attributes.

    + +
    Example
    + +
    var form = $('myform');
    + form.getInputs();       // -> all INPUT elements
    +form.getInputs('text'); // -> only text inputs
    + var buttons = form.getInputs('radio', 'education');
    +// -> only radio buttons of name "education"
    + // now disable these radio buttons:
    +buttons.invoke('disable');
    +
    +
    + +
    Note
    + +

    Elements are returned in the document order, not the +tabindex order.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/request/index.html b/doc/dom/form/prototype/request/index.html new file mode 100644 index 000000000..3c6eee84f --- /dev/null +++ b/doc/dom/form/prototype/request/index.html @@ -0,0 +1,239 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#request +

    + + + + +
    +
    +
    +
    +
    +
    Form#request([options]) → Ajax.Request
    + + + +

    A convenience method for serializing and submitting the form via an +Ajax.Request to the URL of the form's action attribute.

    + +

    The options parameter is passed to the Ajax.Request instance, +allowing one to override the HTTP method and/or specify additional +parameters and callbacks.

    + +
      +
    • If the form has a method attribute, its value is used for the +Ajax.Request method option. If a method option is passed to +request(), it takes precedence over the form's method attribute. If +neither is specified, method defaults to "POST".

    • +
    • Key-value pairs specified in the parameters option (either as a hash +or a query string) will be merged with (and take precedence over) the +serialized form parameters.

    • +
    + +
    Example
    + +

    Suppose you have this HTML form:

    + +
    <form id="person-example" method="POST" action="/user/info">
    +  <fieldset><legend>User info</legend>
    +    <ul>
    +      <li>
    +        <label for="username">Username:</label>
    +        <input type="text" name="username" id="username" value="" />
    +      </li>
    +      <li>
    +        <label for="age">Age:</label>
    +        <input type="text" name="age" id="age" value="" size="3" />
    +      </li>
    +      <li>
    +        <label for="hobbies">Your hobbies are:</label>
    +        <select name="hobbies[]" id="hobbies" multiple="multiple">
    +          <option>coding</option>
    +          <option>swimming</option>
    +          <option>biking</option>
    +          <option>hiking</option>
    +          <option>drawing</option>
    +        </select>
    +      </li>
    +    </ul>
    +    <input type="submit" value="serialize!" />
    +  </fieldset>
    +</form>
    +
    +
    + +

    You can easily post it with Ajax like this:

    + +
    $('person-example').request(); //done - it's posted
    + // do the same with a callback:
    +$('person-example').request({
    +  onComplete: function(){ alert('Form data saved!') }
    +})
    +
    +
    + +

    To override the HTTP method and add some parameters, simply use method +and parameters in the options. In this example we set the method to GET +and set two fixed parameters: +interests and hobbies. The latter already exists in the form but this +value will take precedence.

    + +
    $('person-example').request({
    +  method: 'get',
    +  parameters: { interests:'JavaScript', 'hobbies[]':['programming', 'music'] },
    +  onComplete: function(){ alert('Form data saved!') }
    +})
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/reset/index.html b/doc/dom/form/prototype/reset/index.html new file mode 100644 index 000000000..68bf212c5 --- /dev/null +++ b/doc/dom/form/prototype/reset/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#reset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#reset +

    + + + + +
    +
    +
    +
    +
    +
    Form#reset() → Element
    + + +

    Resets a form to its default values.

    + +

    Example usage:

    + +
    Form.reset('contact')
    + // equivalent:
    +$('contact').reset()
    + // both have the same effect as pressing the reset button
    +
    +
    + +

    This method allows you to programatically reset a form. It is a wrapper +for the reset() method native to HTMLFormElement.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/prototype/serialize/index.html b/doc/dom/form/prototype/serialize/index.html new file mode 100644 index 000000000..044de1ef1 --- /dev/null +++ b/doc/dom/form/prototype/serialize/index.html @@ -0,0 +1,194 @@ + + + + + Prototype v1.7_rc1 API documentation | Form#serialize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Form#serialize +

    + + + + +
    +
    +
    +
    +
    +
    Form#serialize([options]) → String | Object
    +
      +
    • + options + (Object) + – A list of options that affect the return value of the method. +
    • +
    + + +

    Serializes form data to a string suitable for Ajax requests (default +behavior) or, if the hash option evaluates to true, an object hash +where keys are form control names and values are data.

    + +

    Depending of whether or not the hash option evaluates to true, the +result is either an object of the form {name: "johnny", color: "blue"} +or a String of the form "name=johnny&color=blue", suitable for +parameters in an Ajax request. This method mimics the way browsers +serialize forms natively so that form data can be sent without refreshing +the page.

    + +

    See Form.serializeElements for more details on the options.

    + +
    Examples
    + +
    $('person-example').serialize()
    +// -> 'username=sulien&age=22&hobbies=coding&hobbies=hiking'
    + $('person-example').serialize(true)
    +// -> {username: 'sulien', age: '22', hobbies: ['coding', 'hiking']}
    +
    +
    + +
    Notes
    + +

    Disabled form elements are not serialized (as per W3C HTML recommendation). +Also, file inputs are skipped as they cannot be serialized and sent using +only JavaScript.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/request/index.html b/doc/dom/form/request/index.html new file mode 100644 index 000000000..a6ead8fb7 --- /dev/null +++ b/doc/dom/form/request/index.html @@ -0,0 +1,239 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.request + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.request +

    + + + + +
    +
    +
    +
    +
    +
    Form.request(form[, options]) → Ajax.Request
    + + + +

    A convenience method for serializing and submitting the form via an +Ajax.Request to the URL of the form's action attribute.

    + +

    The options parameter is passed to the Ajax.Request instance, +allowing one to override the HTTP method and/or specify additional +parameters and callbacks.

    + +
      +
    • If the form has a method attribute, its value is used for the +Ajax.Request method option. If a method option is passed to +request(), it takes precedence over the form's method attribute. If +neither is specified, method defaults to "POST".

    • +
    • Key-value pairs specified in the parameters option (either as a hash +or a query string) will be merged with (and take precedence over) the +serialized form parameters.

    • +
    + +
    Example
    + +

    Suppose you have this HTML form:

    + +
    <form id="person-example" method="POST" action="/user/info">
    +  <fieldset><legend>User info</legend>
    +    <ul>
    +      <li>
    +        <label for="username">Username:</label>
    +        <input type="text" name="username" id="username" value="" />
    +      </li>
    +      <li>
    +        <label for="age">Age:</label>
    +        <input type="text" name="age" id="age" value="" size="3" />
    +      </li>
    +      <li>
    +        <label for="hobbies">Your hobbies are:</label>
    +        <select name="hobbies[]" id="hobbies" multiple="multiple">
    +          <option>coding</option>
    +          <option>swimming</option>
    +          <option>biking</option>
    +          <option>hiking</option>
    +          <option>drawing</option>
    +        </select>
    +      </li>
    +    </ul>
    +    <input type="submit" value="serialize!" />
    +  </fieldset>
    +</form>
    +
    +
    + +

    You can easily post it with Ajax like this:

    + +
    $('person-example').request(); //done - it's posted
    + // do the same with a callback:
    +$('person-example').request({
    +  onComplete: function(){ alert('Form data saved!') }
    +})
    +
    +
    + +

    To override the HTTP method and add some parameters, simply use method +and parameters in the options. In this example we set the method to GET +and set two fixed parameters: +interests and hobbies. The latter already exists in the form but this +value will take precedence.

    + +
    $('person-example').request({
    +  method: 'get',
    +  parameters: { interests:'JavaScript', 'hobbies[]':['programming', 'music'] },
    +  onComplete: function(){ alert('Form data saved!') }
    +})
    +
    +
    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/reset/index.html b/doc/dom/form/reset/index.html new file mode 100644 index 000000000..91dc27776 --- /dev/null +++ b/doc/dom/form/reset/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.reset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.reset +

    + + + + +
    +
    +
    +
    +
    +
    Form.reset(form) → Element
    + + +

    Resets a form to its default values.

    + +

    Example usage:

    + +
    Form.reset('contact')
    + // equivalent:
    +$('contact').reset()
    + // both have the same effect as pressing the reset button
    +
    +
    + +

    This method allows you to programatically reset a form. It is a wrapper +for the reset() method native to HTMLFormElement.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/serialize/index.html b/doc/dom/form/serialize/index.html new file mode 100644 index 000000000..c24049e3a --- /dev/null +++ b/doc/dom/form/serialize/index.html @@ -0,0 +1,194 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.serialize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.serialize +

    + + + + +
    +
    +
    +
    +
    +
    Form.serialize(form[, options]) → String | Object
    +
      +
    • + options + (Object) + – A list of options that affect the return value of the method. +
    • +
    + + +

    Serializes form data to a string suitable for Ajax requests (default +behavior) or, if the hash option evaluates to true, an object hash +where keys are form control names and values are data.

    + +

    Depending of whether or not the hash option evaluates to true, the +result is either an object of the form {name: "johnny", color: "blue"} +or a String of the form "name=johnny&color=blue", suitable for +parameters in an Ajax request. This method mimics the way browsers +serialize forms natively so that form data can be sent without refreshing +the page.

    + +

    See Form.serializeElements for more details on the options.

    + +
    Examples
    + +
    $('person-example').serialize()
    +// -> 'username=sulien&age=22&hobbies=coding&hobbies=hiking'
    + $('person-example').serialize(true)
    +// -> {username: 'sulien', age: '22', hobbies: ['coding', 'hiking']}
    +
    +
    + +
    Notes
    + +

    Disabled form elements are not serialized (as per W3C HTML recommendation). +Also, file inputs are skipped as they cannot be serialized and sent using +only JavaScript.

    + + + + +

    + This method can be called either as an instance method or as a generic method. + If calling as a generic, pass the instance in as the first argument.

    + +

    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/form/serializeelements/index.html b/doc/dom/form/serializeelements/index.html new file mode 100644 index 000000000..6a60f89ab --- /dev/null +++ b/doc/dom/form/serializeelements/index.html @@ -0,0 +1,228 @@ + + + + + Prototype v1.7_rc1 API documentation | Form.serializeElements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Form.serializeElements +

    + + + + +
    +
    +
    +
    +
    +
    Form.serializeElements(elements[, options]) → String | Object
    +
      +
    • + elements + (Array) + – A collection of elements to include in the serialization. +
    • +
    • + options + (Object) + – (Optional) A set of options that affect the return value of the method. +
    • +
    + + +

    Serialize an array of form elements to an object or string suitable +for Ajax requests.

    + +

    As per the HTML spec, disabled fields are not included.

    + +

    If multiple elements have the same name and we're returning an object, +the value for that key in the object will be an array of the field values +in the order they appeared on the array of elements.

    + +

    The preferred method to serialize a form is Form.serialize. Refer to +it for further information and examples on the hash option. However, +with Form.serializeElements you can serialize specific input +elements of your choice, allowing you to specify a subset of form elements +that you want to serialize data from.

    + +
    The Options
    + +

    The options allow you to control two things: What kind of return +value you get (an object or a string), and whether and which submit +fields are included in that object or string.

    + +

    If you do not supply an options object at all, the options +{ hash: false } are used.

    + +

    If you supply an options object, it may have the following options:

    + +
      +
    • hash (Boolean): true to return a plain object with keys and +values (not a Hash; see below), false to return a String in query +string format. If you supply an options object with no hash member, +hash defaults to true. Note that this is not the same as leaving +off the options object entirely (see above).
    • +
    • submit (Boolean | String): In essence: If you omit this option +the first submit button in the form is included; if you supply false, +no submit buttons are included; if you supply the name of a submit +button, the first button with that name is included. Note that the +false value must really be false, not falsey; +falsey-but-not-false is like omitting the option.
    • +
    + +

    (Deprecated) If you pass in a Boolean instead of an object for +options, it is used as the hash option and all other options are +defaulted.

    + +
    A hash, not a Hash
    + +

    If you opt to receive an object, it is a plain JavaScript object with keys +and values, not a Hash. All JavaScript objects are hashes in the +lower-case sense of the word, which is why the option has that +somewhat-confusing name.

    + +
    Examples
    + +

    To serialize all input elements of type "text":

    + +
    Form.serializeElements( $('myform').getInputs('text') )
    +// -> serialized data
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/index.html b/doc/dom/index.html new file mode 100644 index 000000000..00b1da14d --- /dev/null +++ b/doc/dom/index.html @@ -0,0 +1,208 @@ + + + + + Prototype v1.7_rc1 API documentation | DOM section + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +

    + section DOM section +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to DOM elements, plus other utilities for DOM traversal +and modification.

    + +

    Prototype's DOM extensions represent a large portion of where you'll spend +your time. Prototype adds many convenience methods to elements returned by +the $ function. For instance, you can write

    + +
    $('comments').addClassName('active').show();
    +
    +
    + +

    to get the element with the ID of comments, add a class name to it, and +show it (if it was previously hidden).

    + +

    In other words, Prototype adds "instance" methods to DOM nodes. This is +made possible by direct extension of the backing DOM objects (in browsers +that support it) and by manual extension of individual nodes (in browsers +that do not).

    +
    +
    + + + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      document

      + +

      Prototype extends the built-in document object with several convenience +methods related to events.

      +
    • +
    • +

      Form

      + +

      Utilities for dealing with forms in the DOM.

      +
    • +
    • +

      Abstract

      + +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Element

      + +

      The Element object provides a variety of powerful DOM methods for +interacting with DOM elements — creating them, updating them, +traversing them, etc. You can access these either as methods of Element +itself, passing in the element to work with as the first argument, or as +methods on extended element instances:

      +
    • +
    • +

      Event

      + +

      The namespace for Prototype's event system.

      +
    • +
    • +

      Selector

      + +

      A class that queries the document for elements that match a given CSS +selector.

      +
    • +
    +
    +
    + + +
    + + + +
    + + diff --git a/doc/dom/selector/findchildelements/index.html b/doc/dom/selector/findchildelements/index.html new file mode 100644 index 000000000..6ec837361 --- /dev/null +++ b/doc/dom/selector/findchildelements/index.html @@ -0,0 +1,147 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector.findChildElements + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Selector.findChildElements +

    + + + + +
    +
    +
    +
    +
    +
    Selector.findChildElements(element, expressions) → [Element…]
    + + +

    Searches beneath element for any elements that match the selector +(or selectors) specified in expressions.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/selector/findelement/index.html b/doc/dom/selector/findelement/index.html new file mode 100644 index 000000000..22d1cc43e --- /dev/null +++ b/doc/dom/selector/findelement/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector.findElement + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Selector.findElement +

    + + + + +
    +
    +
    +
    +
    +
    Selector.findElement(elements, expression[, index = 0]) → Element
    Selector.findElement(elements[, index = 0]) → Element
    + + +

    Returns the indexth element in the collection that matches +expression.

    + +

    Returns the indexth element overall if expression is not given.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/selector/index.html b/doc/dom/selector/index.html new file mode 100644 index 000000000..4913dffb0 --- /dev/null +++ b/doc/dom/selector/index.html @@ -0,0 +1,190 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class Selector +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A class that queries the document for elements that match a given CSS +selector.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Selector

    +
    +
    + + + +
    +
    +

    Class methods

    +
    + +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/dom/selector/matchelements/index.html b/doc/dom/selector/matchelements/index.html new file mode 100644 index 000000000..dfc4d7823 --- /dev/null +++ b/doc/dom/selector/matchelements/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector.matchElements + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Selector.matchElements +

    + + + + +
    +
    +
    +
    +
    +
    Selector.matchElements(elements, expression) → [Element…]
    + + +

    Filters the given collection of elements with expression.

    + +

    The only nodes returned will be those that match the given CSS selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/selector/new/index.html b/doc/dom/selector/new/index.html new file mode 100644 index 000000000..1ddb02c0d --- /dev/null +++ b/doc/dom/selector/new/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | new Selector + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + constructor new Selector +

    + + + + +
    +
    +
    +
    +
    +
    new(expression)
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Creates a Selector with the given CSS selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/selector/prototype/findelements/index.html b/doc/dom/selector/prototype/findelements/index.html new file mode 100644 index 000000000..e9b7f4357 --- /dev/null +++ b/doc/dom/selector/prototype/findelements/index.html @@ -0,0 +1,154 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector#findElements + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Selector#findElements +

    + + + + +
    +
    +
    +
    +
    +
    Selector#findElements(root) → [Element…]
    +
      +
    • + root + (Element | document) + – A "scope" to search within. All results will be descendants of this node. +
    • +
    + + +

    Searches the document for elements that match the instance's CSS +selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/dom/selector/prototype/match/index.html b/doc/dom/selector/prototype/match/index.html new file mode 100644 index 000000000..1714c74e8 --- /dev/null +++ b/doc/dom/selector/prototype/match/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | Selector#match + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + instance method Selector#match +

    + + + + +
    +
    +
    +
    +
    +
    Selector#match(element) → Boolean
    + + +

    Tests whether a element matches the instance's CSS selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/images/alias.png b/doc/images/alias.png new file mode 100755 index 000000000..6332fefea Binary files /dev/null and b/doc/images/alias.png differ diff --git a/doc/images/class.png b/doc/images/class.png new file mode 100644 index 000000000..e1510c169 Binary files /dev/null and b/doc/images/class.png differ diff --git a/doc/images/class_deprecated.png b/doc/images/class_deprecated.png new file mode 100644 index 000000000..9b7467990 Binary files /dev/null and b/doc/images/class_deprecated.png differ diff --git a/doc/images/class_method.png b/doc/images/class_method.png new file mode 100644 index 000000000..362e29562 Binary files /dev/null and b/doc/images/class_method.png differ diff --git a/doc/images/class_property.png b/doc/images/class_property.png new file mode 100755 index 000000000..ebaf0e874 Binary files /dev/null and b/doc/images/class_property.png differ diff --git a/doc/images/constant.png b/doc/images/constant.png new file mode 100644 index 000000000..c4295ec0d Binary files /dev/null and b/doc/images/constant.png differ diff --git a/doc/images/constructor.png b/doc/images/constructor.png new file mode 100755 index 000000000..565a9330e Binary files /dev/null and b/doc/images/constructor.png differ diff --git a/doc/images/deprecated.png b/doc/images/deprecated.png new file mode 100644 index 000000000..3f145ccce Binary files /dev/null and b/doc/images/deprecated.png differ diff --git a/doc/images/description.png b/doc/images/description.png new file mode 100755 index 000000000..5c870176d Binary files /dev/null and b/doc/images/description.png differ diff --git a/doc/images/grid.png b/doc/images/grid.png new file mode 100644 index 000000000..151ac265d Binary files /dev/null and b/doc/images/grid.png differ diff --git a/doc/images/header-logo-small.png b/doc/images/header-logo-small.png new file mode 100644 index 000000000..f377977fb Binary files /dev/null and b/doc/images/header-logo-small.png differ diff --git a/doc/images/header-logo.png b/doc/images/header-logo.png new file mode 100644 index 000000000..4f6c7c186 Binary files /dev/null and b/doc/images/header-logo.png differ diff --git a/doc/images/header-stripe-small.png b/doc/images/header-stripe-small.png new file mode 100644 index 000000000..e10464063 Binary files /dev/null and b/doc/images/header-stripe-small.png differ diff --git a/doc/images/header-stripe.png b/doc/images/header-stripe.png new file mode 100644 index 000000000..2254f7c83 Binary files /dev/null and b/doc/images/header-stripe.png differ diff --git a/doc/images/information.png b/doc/images/information.png new file mode 100755 index 000000000..12cd1aef9 Binary files /dev/null and b/doc/images/information.png differ diff --git a/doc/images/instance_method.png b/doc/images/instance_method.png new file mode 100644 index 000000000..f6464ab43 Binary files /dev/null and b/doc/images/instance_method.png differ diff --git a/doc/images/instance_property.png b/doc/images/instance_property.png new file mode 100755 index 000000000..83ec984bd Binary files /dev/null and b/doc/images/instance_property.png differ diff --git a/doc/images/logo.png b/doc/images/logo.png new file mode 100644 index 000000000..6ff25884e Binary files /dev/null and b/doc/images/logo.png differ diff --git a/doc/images/menu-flap.png b/doc/images/menu-flap.png new file mode 100644 index 000000000..4424406b0 Binary files /dev/null and b/doc/images/menu-flap.png differ diff --git a/doc/images/method.png b/doc/images/method.png new file mode 100644 index 000000000..35efa7594 Binary files /dev/null and b/doc/images/method.png differ diff --git a/doc/images/method_deprecated.png b/doc/images/method_deprecated.png new file mode 100644 index 000000000..ee77e485f Binary files /dev/null and b/doc/images/method_deprecated.png differ diff --git a/doc/images/mixin.png b/doc/images/mixin.png new file mode 100644 index 000000000..11a7f8fed Binary files /dev/null and b/doc/images/mixin.png differ diff --git a/doc/images/namespace.png b/doc/images/namespace.png new file mode 100644 index 000000000..f2f7b73dd Binary files /dev/null and b/doc/images/namespace.png differ diff --git a/doc/images/property.png b/doc/images/property.png new file mode 100755 index 000000000..ebaf0e874 Binary files /dev/null and b/doc/images/property.png differ diff --git a/doc/images/related_to.png b/doc/images/related_to.png new file mode 100755 index 000000000..25eacb7c2 Binary files /dev/null and b/doc/images/related_to.png differ diff --git a/doc/images/search-background.png b/doc/images/search-background.png new file mode 100644 index 000000000..76295000a Binary files /dev/null and b/doc/images/search-background.png differ diff --git a/doc/images/section-background.png b/doc/images/section-background.png new file mode 100644 index 000000000..d3cf11e39 Binary files /dev/null and b/doc/images/section-background.png differ diff --git a/doc/images/section.png b/doc/images/section.png new file mode 100644 index 000000000..d9d598569 Binary files /dev/null and b/doc/images/section.png differ diff --git a/doc/images/subclass.png b/doc/images/subclass.png new file mode 100755 index 000000000..9ebf013a2 Binary files /dev/null and b/doc/images/subclass.png differ diff --git a/doc/images/superclass.png b/doc/images/superclass.png new file mode 100755 index 000000000..9ebf013a2 Binary files /dev/null and b/doc/images/superclass.png differ diff --git a/doc/images/tagline.png b/doc/images/tagline.png new file mode 100644 index 000000000..85b366caa Binary files /dev/null and b/doc/images/tagline.png differ diff --git a/doc/images/utility.png b/doc/images/utility.png new file mode 100755 index 000000000..59af16382 Binary files /dev/null and b/doc/images/utility.png differ diff --git a/doc/index.html b/doc/index.html new file mode 100644 index 000000000..de3139008 --- /dev/null +++ b/doc/index.html @@ -0,0 +1,214 @@ + + + + + Prototype v1.7_rc1 API documentation | Home + + + + + + + + + + + + + + + + +
    + + +
    + +
    +

    Prototype

    + +

    An object-oriented JavaScript framework

    + +

    Prototype is a JavaScript framework that aims to ease development of dynamic +web applications. It offers a familiar class-style OO framework, extensive +Ajax support, higher-order programming constructs, and easy DOM manipulation.

    + +

    Targeted platforms

    + +

    Prototype currently targets the following platforms:

    + +
      +
    • Microsoft Internet Explorer for Windows, version 6.0 and higher
    • +
    • Mozilla Firefox 1.5 and higher
    • +
    • Apple Safari 2.0.4 and higher
    • +
    • Opera 9.25 and higher
    • +
    • Chrome 1.0 and higher
    • +
    + +

    Using Prototype

    + +

    To use Prototype in your application, download the latest release from the +Prototype web site (http://prototypejs.org/download) and copy +dist/prototype.js to a suitable location. Then include it in your HTML +like so:

    + +
    <script type="text/javascript" src="/path/to/prototype.js"></script>
    +
    +
    + +

    Building Prototype from source

    + +

    prototype.js is a composite file generated from many source files in +the src/ directory. To build Prototype, you'll need:

    + +
      +
    • a copy of the Prototype source tree, either from a distribution tarball or +from the Git repository (see below)
    • +
    • Ruby 1.8.2 or higher (http://www.ruby-lang.org/)
    • +
    • Rake--Ruby Make (http://rake.rubyforge.org/)
    • +
    • RDoc, if your Ruby distribution does not include it
    • +
    + +

    From the root Prototype directory,

    + +
      +
    • rake dist will preprocess the Prototype source using Sprockets and +generate the composite dist/prototype.js.
    • +
    • rake package will create a distribution tarball in the +pkg/ directory.
    • +
    + +

    Contributing to Prototype

    + +

    Check out the Prototype source with

    + +
    $ git clone git://github.com/sstephenson/prototype.git
    +$ cd prototype
    +$ git submodule init
    +$ git submodule update vendor/sprockets vendor/pdoc vendor/unittest_js
    +
    +
    + +

    Find out how to contribute: http://prototypejs.org/contribute.

    + +

    Documentation

    + +

    Please see the online Prototype API: http://api.prototypejs.org.

    +
    + +
    +
    +

    Sections

    +
    +
    + +
      +
    • +

      + Ajax +

      +

      Prototype's APIs around the XmlHttpRequest object.

      +
    • +
    • +

      + DOM +

      +

      Extensions to DOM elements, plus other utilities for DOM traversal +and modification.

      +
    • +
    • +

      + Language +

      +

      Additions to JavaScript's "standard library" and extensions to +built-in JavaScript objects.

      +
    • +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/javascripts/application.js b/doc/javascripts/application.js new file mode 100644 index 000000000..a0303de26 --- /dev/null +++ b/doc/javascripts/application.js @@ -0,0 +1,478 @@ +//= require + +if (!Prototype || Prototype.Version.indexOf('1.6') !== 0) { + throw "This script requires Prototype >= 1.6."; +} + +Object.isDate = function(object) { + return object instanceof Date; +}; + +/** + * class Cookie + * Creates a cookie. +**/ +var Cookie = Class.create({ + /** + * new Cookie(name, value[, expires]) + * + * - name (String): The name of the cookie. + * - value (String): The value of the cookie. + * - expires (Number | Date): Exact date (or number of days from now) that + * the cookie will expire. + **/ + initialize: function(name, value, expires) { + expires = expires || ""; + if (Object.isNumber(expires)) { + var days = expires; + expires = new Date(); + expires.setTime(expires.getTime() + (days * 24 * 60 * 60 * 1000)); + } + + if (Object.isDate(expires)) + expires = expires.toGMTString(); + + if (!Object.isUndefined(expires) && expires !== "") + expires = "; expires=" + expires; + + this.name = name; + this.value = value; + this.expires = expires; + + document.cookie = name + "=" + value + expires + "; path=/"; + }, + + toString: function() { + return this.value; + }, + + inspect: function() { + return "#".interpolate(this); + } +}); + +/** + * Cookie +**/ +Object.extend(Cookie, { + /** + * Cookie.set(name, value, expires) + * + * Alias of [[Cookie#initialize]]. + **/ + set: function(name, value, expires) { + return new Cookie(name, value, expires); + }, + + /** + * Cookie.get(name) + * + * Returns the value of the cookie with the given name. + * - name (String): The name of the cookie to retrieve. + **/ + get: function(name) { + var c = document.cookie.split(';'); + + for (var i = 0, cookie; i < c.length; i++) { + cookie = c[i].split('='); + if (cookie[0].strip() === name) + return cookie[1].strip(); + } + + return null; + }, + + /** + * Cookie.unset(name) + * + * Deletes a cookie. + * - name (String): The name of the cookie to delete. + * + **/ + unset: function(name) { + return Cookie.set(name, "", -1); + } +}); + +Cookie.erase = Cookie.unset; + + + +if (typeof PDoc === 'undefined') { + window.PDoc = { + Sidebar: {} + }; +} + +// HISTORY MANAGER (sort of) +// Polls for changes to the hash. + +(function() { + var PREVIOUS_HASH = null; + + function poll() { + var hash = window.location.hash; + if (hash && hash !== PREVIOUS_HASH) { + document.fire('hash:changed', { + previous: PREVIOUS_HASH, current: hash + }); + } + PREVIOUS_HASH = hash; + window.setTimeout(arguments.callee, 100); + } + + Event.observe(window, 'load', poll); +})(); + +Object.extend(PDoc.Sidebar, { + getActiveTab: function() { + var activeTab = $('sidebar_tabs').down('.active'); + if (!activeTab) return null; + + var href = activeTab.readAttribute('href'); + return href.endsWith('menu_pane') ? 'menu_pane' : 'search_pane'; + }, + + // Remember the state of the sidebar so it can be restored on the next page. + serialize: function() { + var state = $H({ + activeTab: PDoc.Sidebar.getActiveTab(), + menuScrollOffset: $('menu_pane').scrollTop, + searchScrollOffset: $('search_results').scrollTop, + searchValue: $('search').getValue() + }); + + return escape(state.toJSON()); + }, + + // Restore the tree to a certain point based on a cookie. + restore: function(state) { + try { + state = unescape(state).evalJSON(); + var filterer = $('search').retrieve('filterer'); + filterer.setSearchValue(state.searchValue); + + (function() { + $('menu_pane').scrollTop = state.menuScrollOffset; + $('search_results').scrollTop = state.searchScrollOffset; + }).defer(); + } catch(error) { + console.log(error); + if (!(error instanceof SyntaxError)) throw error; + } + } +}); + + + +// Live API search. +PDoc.Sidebar.Filterer = Class.create({ + initialize: function(element, options) { + this.element = $(element); + this.options = Object.extend( + Object.clone(PDoc.Sidebar.Filterer.DEFAULT_OPTIONS), + options || {} + ); + + // The browser's "helpful" auto-complete gets in the way. + this.element.writeAttribute("autocomplete", "off"); + this.element.setValue(''); + + // Hitting "enter" should do nothing. + this.element.up('form').observe("submit", Event.stop); + + this.menu = this.options.menu; + this.links = this.menu.select('a'); + + this.resultsElement = this.options.resultsElement; + + this.observers = { + filter: this.filter.bind(this), + keydown: this.keydown.bind(this), + keyup: this.keyup.bind(this) + }; + + this.menu.setStyle({ opacity: 0.9 }); + this.addObservers(); + }, + + addObservers: function() { + this.element.observe('keyup', this.observers.filter); + }, + + // Called whenever the list of results needs to update as a result of a + // changed search key. + filter: function(event) { + // Clear the text box on ESC. + if (event.keyCode && event.keyCode === Event.KEY_ESC) { + this.element.setValue(''); + } + + if (PDoc.Sidebar.Filterer.INTERCEPT_KEYS.include(event.keyCode)) + return; + + // If there's nothing in the text box, clear the results list. + var value = $F(this.element).strip().toLowerCase(); + if (value === '') { + this.emptyResults(); + this.hideResults(); + return; + } + + var urls = this.findURLs(value); + this.buildResults(urls); + }, + + setSearchValue: function(value) { + this.element.setValue(value); + if (value.strip() === "") { + PDoc.Sidebar.Tabs.setActiveTab(0); + return; + } + this.buildResults(this.findURLs(value)); + }, + + // Given a key, finds all the PDoc objects that match. + findURLs: function(str) { + var results = []; + for (var name in PDoc.elements) { + if (name.toLowerCase().include(str.toLowerCase())) + results.push(PDoc.elements[name]); + } + return results; + }, + + buildResults: function(results) { + this.emptyResults(); + + results.each( function(result) { + var li = this._buildResult(result); + this.resultsElement.appendChild(li); + }, this); + this.showResults(); + }, + + _buildResult: function(obj) { + var li = new Element('li', { 'class': 'menu-item' }); + var a = new Element('a', { + 'class': obj.type.gsub(/\s/, '-'), + 'href': PDoc.pathPrefix + obj.path + }).update(obj.name); + + li.appendChild(a); + return li; + }, + + emptyResults: function() { + this.resultsElement.update(); + }, + + hideResults: function() { + PDoc.Sidebar.Tabs.setActiveTab(0); + //this.resultsElement.hide(); + document.stopObserving('keydown', this.observers.keydown); + document.stopObserving('keyup', this.observers.keyup); + }, + + showResults: function() { + PDoc.Sidebar.Tabs.setActiveTab(1); + //this.resultsElement.show(); + document.stopObserving('keydown', this.observers.keydown); + this.element.stopObserving('keyup', this.observers.keyup); + this.element.observe('keydown', this.observers.keydown); + document.observe('keyup', this.observers.keyup); + }, + + keydown: function(event) { + if (!PDoc.Sidebar.Filterer.INTERCEPT_KEYS.include(event.keyCode)) + return; + + // Also ignore if any modifier keys are present. + if (event.shiftKey || event.ctrlKey || event.altKey || event.metaKey) + return; + + event.stop(); + + if (event.keyCode === Event.KEY_RETURN) { + // Follow the highlighted item, unless there is none. + if (!this.highlighted) return; + var a = this.highlighted.down('a'); + if (a) { + window.location.href = a.href; + } + } else if ([Event.KEY_UP, Event.KEY_DOWN].include(event.keyCode)) { + // Is an arrow key. + var direction = (Event.KEY_DOWN === event.keyCode) ? 1 : -1; + this.highlighted = this.moveHighlight(direction); + + if (!Prototype.Browser.WebKit) { + // If up/down key is held down, list should keep scrolling. + // WebKit does this automatically because it fires the keydown + // event over and over. + this._scrollTimer = window.setTimeout( + this.scrollList.bind(this, direction), 1000); + } + } + }, + + keyup: function(event) { + if (this._scrollTimer) { + window.clearTimeout(this._scrollTimer); + } + }, + + moveHighlight: function(direction) { + if (!this.highlighted) { + // If there is none, highlight the first result. + this.highlighted = + this.resultsElement.down('li').addClassName('highlighted'); + } else { + var method = (direction === 1) ? 'next' : 'previous'; + this.highlighted.removeClassName('highlighted'); + var adjacent = this.highlighted[method]('li'); + // If there isn't an adjacent one, we're at the top or bottom + // of the list. Flip it. + if (!adjacent) { + adjacent = method == 'next' ? this.resultsElement.down('li') : + this.resultsElement.down('li:last-of-type'); + } + adjacent.addClassName('highlighted'); + this.highlighted = adjacent; + } + + var h = this.highlighted, r = this.resultsElement; + + var distanceToBottom = h.offsetTop + h.offsetHeight; + if (distanceToBottom > (r.offsetHeight + r.scrollTop)) { + // Item is below the visible frame. + r.scrollTop = distanceToBottom - r.offsetHeight; + } else if (h.offsetTop < r.scrollTop) { + // Item is above the visible frame. + r.scrollTop = h.offsetTop; + } + + return this.highlighted; + }, + + scrollList: function(direction) { + this.moveHighlight(direction); + this._scrollTimer = window.setTimeout( + this.scrollList.bind(this, direction), 100); + } +}); + +Object.extend(PDoc.Sidebar.Filterer, { + INTERCEPT_KEYS: [Event.KEY_UP, Event.KEY_DOWN, Event.KEY_RETURN], + DEFAULT_OPTIONS: { + interval: 0.1, + resultsElement: '.search-results' + } +}); + + +Form.GhostedField = Class.create({ + initialize: function(element, title, options) { + options = options || {}; + + this.element = $(element); + this.title = title; + + this.isGhosted = true; + + if (options.cloak) { + + // Wrap the native getValue function so that it never returns the + // ghosted value. This is optional because it presumes the ghosted + // value isn't valid input for the field. + this.element.getValue = this.element.getValue.wrap(this.wrappedGetValue.bind(this)); + } + + this.addObservers(); + + this.onBlur(); + }, + + wrappedGetValue: function($proceed) { + var value = $proceed(); + return value === this.title ? "" : value; + }, + + addObservers: function() { + this.element.observe('focus', this.onFocus.bind(this)); + this.element.observe('blur', this.onBlur.bind(this)); + + var form = this.element.up('form'); + if (form) { + form.observe('submit', this.onSubmit.bind(this)); + } + + // Firefox's bfcache means that form fields need to be re-initialized + // when you hit the "back" button to return to the page. + if (Prototype.Browser.Gecko) { + window.addEventListener('pageshow', this.onBlur.bind(this), false); + } + }, + + onFocus: function() { + if (this.isGhosted) { + this.element.setValue(''); + this.setGhosted(false); + } + }, + + onBlur: function() { + var value = this.element.getValue(); + if (value.blank() || value == this.title) { + this.setGhosted(true); + } else { + this.setGhosted(false); + } + }, + + setGhosted: function(isGhosted) { + this.isGhosted = isGhosted; + this.element[isGhosted ? 'addClassName' : 'removeClassName']('ghosted'); + if (isGhosted) { + this.element.setValue(this.title); + } + }, + + // Hook into the enclosing form's `onsubmit` event so that we clear any + // ghosted text before the form is sent. + onSubmit: function() { + if (this.isGhosted) { + this.element.setValue(''); + } + } +}); + +document.observe('dom:loaded', function() { + PDoc.Sidebar.Tabs = new Control.Tabs($('sidebar_tabs')); + + var searchField = $('search'); + + if (searchField) { + var filterer = new PDoc.Sidebar.Filterer(searchField, { + menu: $('api_menu'), + resultsElement: $('search_results') + }); + searchField.store('filterer', filterer); + } + + // Prevent horizontal scrolling in scrollable sidebar areas. + $$('.scrollable').invoke('observe', 'scroll', function() { + this.scrollLeft = 0; + }); + + var sidebarState = Cookie.get('sidebar_state'); + if (sidebarState) { + PDoc.Sidebar.restore(sidebarState); + } + + new Form.GhostedField(searchField, searchField.getAttribute('title'), + { cloak: true }); +}); + +Event.observe(window, 'unload', function() { + Cookie.set('sidebar_state', PDoc.Sidebar.serialize()); +}); \ No newline at end of file diff --git a/doc/javascripts/controls.js b/doc/javascripts/controls.js new file mode 100644 index 000000000..fbc4418b8 --- /dev/null +++ b/doc/javascripts/controls.js @@ -0,0 +1,963 @@ +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) +// Contributors: +// Richard Livsey +// Rahul Bhargava +// Rob Wills +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// Autocompleter.Base handles all the autocompletion functionality +// that's independent of the data source for autocompletion. This +// includes drawing the autocompletion menu, observing keyboard +// and mouse events, and similar. +// +// Specific autocompleters need to provide, at the very least, +// a getUpdatedChoices function that will be invoked every time +// the text inside the monitored textbox changes. This method +// should get the text for which to provide autocompletion by +// invoking this.getToken(), NOT by directly accessing +// this.element.value. This is to allow incremental tokenized +// autocompletion. Specific auto-completion logic (AJAX, etc) +// belongs in getUpdatedChoices. +// +// Tokenized incremental autocompletion is enabled automatically +// when an autocompleter is instantiated with the 'tokens' option +// in the options parameter, e.g.: +// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); +// will incrementally autocomplete with a comma as the token. +// Additionally, ',' in the above example can be replaced with +// a token array, e.g. { tokens: [',', '\n'] } which +// enables autocompletion on multiple tokens. This is most +// useful when one of the tokens is \n (a newline), as it +// allows smart autocompletion after linebreaks. + +if(typeof Effect == 'undefined') + throw("controls.js requires including script.aculo.us' effects.js library"); + +var Autocompleter = { } +Autocompleter.Base = Class.create({ + baseInitialize: function(element, update, options) { + element = $(element) + this.element = element; + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; + this.entryCount = 0; + this.oldElementValue = this.element.value; + + if(this.setOptions) + this.setOptions(options); + else + this.options = options || { }; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || + function(element, update){ + if(!update.style.position || update.style.position=='absolute') { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update,{duration:0.15}); + }; + this.options.onHide = this.options.onHide || + function(element, update){ new Effect.Fade(update,{duration:0.15}) }; + + if(typeof(this.options.tokens) == 'string') + this.options.tokens = new Array(this.options.tokens); + // Force carriage returns as token delimiters anyway + if (!this.options.tokens.include('\n')) + this.options.tokens.push('\n'); + + this.observer = null; + + this.element.setAttribute('autocomplete','off'); + + Element.hide(this.update); + + Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() { + if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); + if(!this.iefix && + (Prototype.Browser.IE) && + (Element.getStyle(this.update, 'position')=='absolute')) { + new Insertion.After(this.update, + ''); + this.iefix = $(this.update.id+'_iefix'); + } + if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() { + this.stopIndicator(); + if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); + if(this.iefix) Element.hide(this.iefix); + }, + + startIndicator: function() { + if(this.options.indicator) Element.show(this.options.indicator); + }, + + stopIndicator: function() { + if(this.options.indicator) Element.hide(this.options.indicator); + }, + + onKeyPress: function(event) { + if(this.active) + switch(event.keyCode) { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + Event.stop(event); + return; + } + else + if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; + + this.changed = true; + this.hasFocus = true; + + if(this.observer) clearTimeout(this.observer); + this.observer = + setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); + }, + + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function(event) { + var element = Event.findElement(event, 'LI'); + if(this.index != element.autocompleteIndex) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function(event) { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; + this.selectEntry(); + this.hide(); + }, + + onBlur: function(event) { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() { + if(this.entryCount > 0) { + for (var i = 0; i < this.entryCount; i++) + this.index==i ? + Element.addClassName(this.getEntry(i),"selected") : + Element.removeClassName(this.getEntry(i),"selected"); + if(this.hasFocus) { + this.show(); + this.active = true; + } + } else { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() { + if(this.index > 0) this.index-- + else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() { + if(this.index < this.entryCount-1) this.index++ + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function(index) { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() { + return this.getEntry(this.index); + }, + + selectEntry: function() { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function(selectedElement) { + if (this.options.updateElement) { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if (this.options.select) { + var nodes = $(selectedElement).select('.' + this.options.select) || []; + if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); + } else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var bounds = this.getTokenBounds(); + if (bounds[0] != -1) { + var newValue = this.element.value.substr(0, bounds[0]); + var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/); + if (whitespace) + newValue += whitespace[0]; + this.element.value = newValue + value + this.element.value.substr(bounds[1]); + } else { + this.element.value = value; + } + this.oldElementValue = this.element.value; + this.element.focus(); + + if (this.options.afterUpdateElement) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function(choices) { + if(!this.changed && this.hasFocus) { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.down()); + + if(this.update.firstChild && this.update.down().childNodes) { + this.entryCount = + this.update.down().childNodes.length; + for (var i = 0; i < this.entryCount; i++) { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } else { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if(this.entryCount==1 && this.options.autoSelect) { + this.selectEntry(); + this.hide(); + } else { + this.render(); + } + } + }, + + addObservers: function(element) { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() { + this.changed = false; + this.tokenBounds = null; + if(this.getToken().length>=this.options.minChars) { + this.getUpdatedChoices(); + } else { + this.active = false; + this.hide(); + } + this.oldElementValue = this.element.value; + }, + + getToken: function() { + var bounds = this.getTokenBounds(); + return this.element.value.substring(bounds[0], bounds[1]).strip(); + }, + + getTokenBounds: function() { + if (null != this.tokenBounds) return this.tokenBounds; + var value = this.element.value; + if (value.strip().empty()) return [-1, 0]; + var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue); + var offset = (diff == this.oldElementValue.length ? 1 : 0); + var prevTokenPos = -1, nextTokenPos = value.length; + var tp; + for (var index = 0, l = this.options.tokens.length; index < l; ++index) { + tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1); + if (tp > prevTokenPos) prevTokenPos = tp; + tp = value.indexOf(this.options.tokens[index], diff + offset); + if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp; + } + return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]); + } +}); + +Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) { + var boundary = Math.min(newS.length, oldS.length); + for (var index = 0; index < boundary; ++index) + if (newS[index] != oldS[index]) + return index; + return boundary; +}; + +Ajax.Autocompleter = Class.create(Autocompleter.Base, { + initialize: function(element, update, url, options) { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() { + this.startIndicator(); + + var entry = encodeURIComponent(this.options.paramName) + '=' + + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? + this.options.callback(this.element, entry) : entry; + + if(this.options.defaultParams) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function(request) { + this.updateChoices(request.responseText); + } +}); + +// The local array autocompleter. Used when you'd prefer to +// inject an array of autocompletion options into the page, rather +// than sending out Ajax queries, which can be quite slow sometimes. +// +// The constructor takes four parameters. The first two are, as usual, +// the id of the monitored textbox, and id of the autocompletion menu. +// The third is the array you want to autocomplete from, and the fourth +// is the options block. +// +// Extra local autocompletion options: +// - choices - How many autocompletion choices to offer +// +// - partialSearch - If false, the autocompleter will match entered +// text only at the beginning of strings in the +// autocomplete array. Defaults to true, which will +// match text at the beginning of any *word* in the +// strings in the autocomplete array. If you want to +// search anywhere in the string, additionally set +// the option fullSearch to true (default: off). +// +// - fullSsearch - Search anywhere in autocomplete array strings. +// +// - partialChars - How many characters to enter before triggering +// a partial match (unlike minChars, which defines +// how many characters are required to do any match +// at all). Defaults to 2. +// +// - ignoreCase - Whether to ignore case when autocompleting. +// Defaults to true. +// +// It's possible to pass in a custom function as the 'selector' +// option, if you prefer to write your own autocompletion logic. +// In that case, the other options above will not apply unless +// you support them. + +Autocompleter.Local = Class.create(Autocompleter.Base, { + initialize: function(element, update, array, options) { + this.baseInitialize(element, update, options); + this.options.array = array; + }, + + getUpdatedChoices: function() { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function(options) { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function(instance) { + var ret = []; // Beginning matches + var partial = []; // Inside matches + var entry = instance.getToken(); + var count = 0; + + for (var i = 0; i < instance.options.array.length && + ret.length < instance.options.choices ; i++) { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase()) : + elem.indexOf(entry); + + while (foundPos != -1) { + if (foundPos == 0 && elem.length != entry.length) { + ret.push("
  • " + elem.substr(0, entry.length) + "" + + elem.substr(entry.length) + "
  • "); + break; + } else if (entry.length >= instance.options.partialChars && + instance.options.partialSearch && foundPos != -1) { + if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { + partial.push("
  • " + elem.substr(0, foundPos) + "" + + elem.substr(foundPos, entry.length) + "" + elem.substr( + foundPos + entry.length) + "
  • "); + break; + } + } + + foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : + elem.indexOf(entry, foundPos + 1); + + } + } + if (partial.length) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) + return "
      " + ret.join('') + "
    "; + } + }, options || { }); + } +}); + +// AJAX in-place editor and collection editor +// Full rewrite by Christophe Porteneuve (April 2007). + +// Use this if you notice weird scrolling problems on some browsers, +// the DOM might be a bit confused when this gets called so do this +// waits 1 ms (with setTimeout) until it does the activation +Field.scrollFreeActivate = function(field) { + setTimeout(function() { + Field.activate(field); + }, 1); +} + +Ajax.InPlaceEditor = Class.create({ + initialize: function(element, url, options) { + this.url = url; + this.element = element = $(element); + this.prepareOptions(); + this._controls = { }; + arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!! + Object.extend(this.options, options || { }); + if (!this.options.formId && this.element.id) { + this.options.formId = this.element.id + '-inplaceeditor'; + if ($(this.options.formId)) + this.options.formId = ''; + } + if (this.options.externalControl) + this.options.externalControl = $(this.options.externalControl); + if (!this.options.externalControl) + this.options.externalControlOnly = false; + this._originalBackground = this.element.getStyle('background-color') || 'transparent'; + this.element.title = this.options.clickToEditText; + this._boundCancelHandler = this.handleFormCancellation.bind(this); + this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this); + this._boundFailureHandler = this.handleAJAXFailure.bind(this); + this._boundSubmitHandler = this.handleFormSubmission.bind(this); + this._boundWrapperHandler = this.wrapUp.bind(this); + this.registerListeners(); + }, + checkForEscapeOrReturn: function(e) { + if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return; + if (Event.KEY_ESC == e.keyCode) + this.handleFormCancellation(e); + else if (Event.KEY_RETURN == e.keyCode) + this.handleFormSubmission(e); + }, + createControl: function(mode, handler, extraClasses) { + var control = this.options[mode + 'Control']; + var text = this.options[mode + 'Text']; + if ('button' == control) { + var btn = document.createElement('input'); + btn.type = 'submit'; + btn.value = text; + btn.className = 'editor_' + mode + '_button'; + if ('cancel' == mode) + btn.onclick = this._boundCancelHandler; + this._form.appendChild(btn); + this._controls[mode] = btn; + } else if ('link' == control) { + var link = document.createElement('a'); + link.href = '#'; + link.appendChild(document.createTextNode(text)); + link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler; + link.className = 'editor_' + mode + '_link'; + if (extraClasses) + link.className += ' ' + extraClasses; + this._form.appendChild(link); + this._controls[mode] = link; + } + }, + createEditField: function() { + var text = (this.options.loadTextURL ? this.options.loadingText : this.getText()); + var fld; + if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) { + fld = document.createElement('input'); + fld.type = 'text'; + var size = this.options.size || this.options.cols || 0; + if (0 < size) fld.size = size; + } else { + fld = document.createElement('textarea'); + fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows); + fld.cols = this.options.cols || 40; + } + fld.name = this.options.paramName; + fld.value = text; // No HTML breaks conversion anymore + fld.className = 'editor_field'; + if (this.options.submitOnBlur) + fld.onblur = this._boundSubmitHandler; + this._controls.editor = fld; + if (this.options.loadTextURL) + this.loadExternalText(); + this._form.appendChild(this._controls.editor); + }, + createForm: function() { + var ipe = this; + function addText(mode, condition) { + var text = ipe.options['text' + mode + 'Controls']; + if (!text || condition === false) return; + ipe._form.appendChild(document.createTextNode(text)); + }; + this._form = $(document.createElement('form')); + this._form.id = this.options.formId; + this._form.addClassName(this.options.formClassName); + this._form.onsubmit = this._boundSubmitHandler; + this.createEditField(); + if ('textarea' == this._controls.editor.tagName.toLowerCase()) + this._form.appendChild(document.createElement('br')); + if (this.options.onFormCustomization) + this.options.onFormCustomization(this, this._form); + addText('Before', this.options.okControl || this.options.cancelControl); + this.createControl('ok', this._boundSubmitHandler); + addText('Between', this.options.okControl && this.options.cancelControl); + this.createControl('cancel', this._boundCancelHandler, 'editor_cancel'); + addText('After', this.options.okControl || this.options.cancelControl); + }, + destroy: function() { + if (this._oldInnerHTML) + this.element.innerHTML = this._oldInnerHTML; + this.leaveEditMode(); + this.unregisterListeners(); + }, + enterEditMode: function(e) { + if (this._saving || this._editing) return; + this._editing = true; + this.triggerCallback('onEnterEditMode'); + if (this.options.externalControl) + this.options.externalControl.hide(); + this.element.hide(); + this.createForm(); + this.element.parentNode.insertBefore(this._form, this.element); + if (!this.options.loadTextURL) + this.postProcessEditField(); + if (e) Event.stop(e); + }, + enterHover: function(e) { + if (this.options.hoverClassName) + this.element.addClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onEnterHover'); + }, + getText: function() { + return this.element.innerHTML; + }, + handleAJAXFailure: function(transport) { + this.triggerCallback('onFailure', transport); + if (this._oldInnerHTML) { + this.element.innerHTML = this._oldInnerHTML; + this._oldInnerHTML = null; + } + }, + handleFormCancellation: function(e) { + this.wrapUp(); + if (e) Event.stop(e); + }, + handleFormSubmission: function(e) { + var form = this._form; + var value = $F(this._controls.editor); + this.prepareSubmission(); + var params = this.options.callback(form, value) || ''; + if (Object.isString(params)) + params = params.toQueryParams(); + params.editorId = this.element.id; + if (this.options.htmlResponse) { + var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Updater({ success: this.element }, this.url, options); + } else { + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: params, + onComplete: this._boundWrapperHandler, + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.url, options); + } + if (e) Event.stop(e); + }, + leaveEditMode: function() { + this.element.removeClassName(this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + if (this.options.externalControl) + this.options.externalControl.show(); + this._saving = false; + this._editing = false; + this._oldInnerHTML = null; + this.triggerCallback('onLeaveEditMode'); + }, + leaveHover: function(e) { + if (this.options.hoverClassName) + this.element.removeClassName(this.options.hoverClassName); + if (this._saving) return; + this.triggerCallback('onLeaveHover'); + }, + loadExternalText: function() { + this._form.addClassName(this.options.loadingClassName); + this._controls.editor.disabled = true; + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._form.removeClassName(this.options.loadingClassName); + var text = transport.responseText; + if (this.options.stripLoadedTextTags) + text = text.stripTags(); + this._controls.editor.value = text; + this._controls.editor.disabled = false; + this.postProcessEditField(); + }.bind(this), + onFailure: this._boundFailureHandler + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + postProcessEditField: function() { + var fpc = this.options.fieldPostCreation; + if (fpc) + $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate'](); + }, + prepareOptions: function() { + this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions); + Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks); + [this._extraDefaultOptions].flatten().compact().each(function(defs) { + Object.extend(this.options, defs); + }.bind(this)); + }, + prepareSubmission: function() { + this._saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + registerListeners: function() { + this._listeners = { }; + var listener; + $H(Ajax.InPlaceEditor.Listeners).each(function(pair) { + listener = this[pair.value].bind(this); + this._listeners[pair.key] = listener; + if (!this.options.externalControlOnly) + this.element.observe(pair.key, listener); + if (this.options.externalControl) + this.options.externalControl.observe(pair.key, listener); + }.bind(this)); + }, + removeForm: function() { + if (!this._form) return; + this._form.remove(); + this._form = null; + this._controls = { }; + }, + showSaving: function() { + this._oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + this.element.addClassName(this.options.savingClassName); + this.element.style.backgroundColor = this._originalBackground; + this.element.show(); + }, + triggerCallback: function(cbName, arg) { + if ('function' == typeof this.options[cbName]) { + this.options[cbName](this, arg); + } + }, + unregisterListeners: function() { + $H(this._listeners).each(function(pair) { + if (!this.options.externalControlOnly) + this.element.stopObserving(pair.key, pair.value); + if (this.options.externalControl) + this.options.externalControl.stopObserving(pair.key, pair.value); + }.bind(this)); + }, + wrapUp: function(transport) { + this.leaveEditMode(); + // Can't use triggerCallback due to backward compatibility: requires + // binding + direct element + this._boundComplete(transport, this.element); + } +}); + +Object.extend(Ajax.InPlaceEditor.prototype, { + dispose: Ajax.InPlaceEditor.prototype.destroy +}); + +Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, { + initialize: function($super, element, url, options) { + this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions; + $super(element, url, options); + }, + + createEditField: function() { + var list = document.createElement('select'); + list.name = this.options.paramName; + list.size = 1; + this._controls.editor = list; + this._collection = this.options.collection || []; + if (this.options.loadCollectionURL) + this.loadCollection(); + else + this.checkForExternalText(); + this._form.appendChild(this._controls.editor); + }, + + loadCollection: function() { + this._form.addClassName(this.options.loadingClassName); + this.showLoadingText(this.options.loadingCollectionText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + var js = transport.responseText.strip(); + if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check + throw 'Server returned an invalid collection representation.'; + this._collection = eval(js); + this.checkForExternalText(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadCollectionURL, options); + }, + + showLoadingText: function(text) { + this._controls.editor.disabled = true; + var tempOption = this._controls.editor.firstChild; + if (!tempOption) { + tempOption = document.createElement('option'); + tempOption.value = ''; + this._controls.editor.appendChild(tempOption); + tempOption.selected = true; + } + tempOption.update((text || '').stripScripts().stripTags()); + }, + + checkForExternalText: function() { + this._text = this.getText(); + if (this.options.loadTextURL) + this.loadExternalText(); + else + this.buildOptionList(); + }, + + loadExternalText: function() { + this.showLoadingText(this.options.loadingText); + var options = Object.extend({ method: 'get' }, this.options.ajaxOptions); + Object.extend(options, { + parameters: 'editorId=' + encodeURIComponent(this.element.id), + onComplete: Prototype.emptyFunction, + onSuccess: function(transport) { + this._text = transport.responseText.strip(); + this.buildOptionList(); + }.bind(this), + onFailure: this.onFailure + }); + new Ajax.Request(this.options.loadTextURL, options); + }, + + buildOptionList: function() { + this._form.removeClassName(this.options.loadingClassName); + this._collection = this._collection.map(function(entry) { + return 2 === entry.length ? entry : [entry, entry].flatten(); + }); + var marker = ('value' in this.options) ? this.options.value : this._text; + var textFound = this._collection.any(function(entry) { + return entry[0] == marker; + }.bind(this)); + this._controls.editor.update(''); + var option; + this._collection.each(function(entry, index) { + option = document.createElement('option'); + option.value = entry[0]; + option.selected = textFound ? entry[0] == marker : 0 == index; + option.appendChild(document.createTextNode(entry[1])); + this._controls.editor.appendChild(option); + }.bind(this)); + this._controls.editor.disabled = false; + Field.scrollFreeActivate(this._controls.editor); + } +}); + +//**** DEPRECATION LAYER FOR InPlace[Collection]Editor! **** +//**** This only exists for a while, in order to let **** +//**** users adapt to the new API. Read up on the new **** +//**** API and convert your code to it ASAP! **** + +Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) { + if (!options) return; + function fallback(name, expr) { + if (name in options || expr === undefined) return; + options[name] = expr; + }; + fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' : + options.cancelLink == options.cancelButton == false ? false : undefined))); + fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' : + options.okLink == options.okButton == false ? false : undefined))); + fallback('highlightColor', options.highlightcolor); + fallback('highlightEndColor', options.highlightendcolor); +}; + +Object.extend(Ajax.InPlaceEditor, { + DefaultOptions: { + ajaxOptions: { }, + autoRows: 3, // Use when multi-line w/ rows == 1 + cancelControl: 'link', // 'link'|'button'|false + cancelText: 'cancel', + clickToEditText: 'Click to edit', + externalControl: null, // id|elt + externalControlOnly: false, + fieldPostCreation: 'activate', // 'activate'|'focus'|false + formClassName: 'inplaceeditor-form', + formId: null, // id|elt + highlightColor: '#ffff99', + highlightEndColor: '#ffffff', + hoverClassName: '', + htmlResponse: true, + loadingClassName: 'inplaceeditor-loading', + loadingText: 'Loading...', + okControl: 'button', // 'link'|'button'|false + okText: 'ok', + paramName: 'value', + rows: 1, // If 1 and multi-line, uses autoRows + savingClassName: 'inplaceeditor-saving', + savingText: 'Saving...', + size: 0, + stripLoadedTextTags: false, + submitOnBlur: false, + textAfterControls: '', + textBeforeControls: '', + textBetweenControls: '' + }, + DefaultCallbacks: { + callback: function(form) { + return Form.serialize(form); + }, + onComplete: function(transport, element) { + // For backward compatibility, this one is bound to the IPE, and passes + // the element directly. It was too often customized, so we don't break it. + new Effect.Highlight(element, { + startcolor: this.options.highlightColor, keepBackgroundImage: true }); + }, + onEnterEditMode: null, + onEnterHover: function(ipe) { + ipe.element.style.backgroundColor = ipe.options.highlightColor; + if (ipe._effect) + ipe._effect.cancel(); + }, + onFailure: function(transport, ipe) { + alert('Error communication with the server: ' + transport.responseText.stripTags()); + }, + onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls. + onLeaveEditMode: null, + onLeaveHover: function(ipe) { + ipe._effect = new Effect.Highlight(ipe.element, { + startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor, + restorecolor: ipe._originalBackground, keepBackgroundImage: true + }); + } + }, + Listeners: { + click: 'enterEditMode', + keydown: 'checkForEscapeOrReturn', + mouseover: 'enterHover', + mouseout: 'leaveHover' + } +}); + +Ajax.InPlaceCollectionEditor.DefaultOptions = { + loadingCollectionText: 'Loading options...' +}; + +// Delayed observer, like Form.Element.Observer, +// but waits for delay after last key input +// Ideal for live-search fields + +Form.Element.DelayedObserver = Class.create({ + initialize: function(element, delay, callback) { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function(event) { + if(this.lastValue == $F(this.element)) return; + if(this.timer) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() { + this.timer = null; + this.callback(this.element, $F(this.element)); + } +}); diff --git a/doc/javascripts/effects.js b/doc/javascripts/effects.js new file mode 100644 index 000000000..718a88d21 --- /dev/null +++ b/doc/javascripts/effects.js @@ -0,0 +1,1120 @@ +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Contributors: +// Justin Palmer (http://encytemedia.com/) +// Mark Pilgrim (http://diveintomark.org/) +// Martin Bialasinki +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// converts rgb() and #xxx to #xxxxxx format, +// returns self (or first argument) if not convertable +String.prototype.parseColor = function() { + var color = '#'; + if (this.slice(0,4) == 'rgb(') { + var cols = this.slice(4,this.length-1).split(','); + var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3); + } else { + if (this.slice(0,1) == '#') { + if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase(); + if (this.length==7) color = this.toLowerCase(); + } + } + return (color.length==7 ? color : (arguments[0] || this)); +}; + +/*--------------------------------------------------------------------------*/ + +Element.collectTextNodes = function(element) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + (node.hasChildNodes() ? Element.collectTextNodes(node) : '')); + }).flatten().join(''); +}; + +Element.collectTextNodesIgnoreClass = function(element, className) { + return $A($(element).childNodes).collect( function(node) { + return (node.nodeType==3 ? node.nodeValue : + ((node.hasChildNodes() && !Element.hasClassName(node,className)) ? + Element.collectTextNodesIgnoreClass(node, className) : '')); + }).flatten().join(''); +}; + +Element.setContentZoom = function(element, percent) { + element = $(element); + element.setStyle({fontSize: (percent/100) + 'em'}); + if (Prototype.Browser.WebKit) window.scrollBy(0,0); + return element; +}; + +Element.getInlineOpacity = function(element){ + return $(element).style.opacity || ''; +}; + +Element.forceRerendering = function(element) { + try { + element = $(element); + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch(e) { } +}; + +/*--------------------------------------------------------------------------*/ + +var Effect = { + _elementDoesNotExistError: { + name: 'ElementDoesNotExistError', + message: 'The specified DOM element does not exist, but is required for this effect to operate' + }, + Transitions: { + linear: Prototype.K, + sinoidal: function(pos) { + return (-Math.cos(pos*Math.PI)/2) + 0.5; + }, + reverse: function(pos) { + return 1-pos; + }, + flicker: function(pos) { + var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + return pos > 1 ? 1 : pos; + }, + wobble: function(pos) { + return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; + }, + pulse: function(pos, pulses) { + pulses = pulses || 5; + return ( + ((pos % (1/pulses)) * pulses).round() == 0 ? + ((pos * pulses * 2) - (pos * pulses * 2).floor()) : + 1 - ((pos * pulses * 2) - (pos * pulses * 2).floor()) + ); + }, + spring: function(pos) { + return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6)); + }, + none: function(pos) { + return 0; + }, + full: function(pos) { + return 1; + } + }, + DefaultOptions: { + duration: 1.0, // seconds + fps: 100, // 100= assume 66fps max. + sync: false, // true for combining + from: 0.0, + to: 1.0, + delay: 0.0, + queue: 'parallel' + }, + tagifyText: function(element) { + var tagifyStyle = 'position:relative'; + if (Prototype.Browser.IE) tagifyStyle += ';zoom:1'; + + element = $(element); + $A(element.childNodes).each( function(child) { + if (child.nodeType==3) { + child.nodeValue.toArray().each( function(character) { + element.insertBefore( + new Element('span', {style: tagifyStyle}).update( + character == ' ' ? String.fromCharCode(160) : character), + child); + }); + Element.remove(child); + } + }); + }, + multiple: function(element, effect) { + var elements; + if (((typeof element == 'object') || + Object.isFunction(element)) && + (element.length)) + elements = element; + else + elements = $(element).childNodes; + + var options = Object.extend({ + speed: 0.1, + delay: 0.0 + }, arguments[2] || { }); + var masterDelay = options.delay; + + $A(elements).each( function(element, index) { + new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay })); + }); + }, + PAIRS: { + 'slide': ['SlideDown','SlideUp'], + 'blind': ['BlindDown','BlindUp'], + 'appear': ['Appear','Fade'] + }, + toggle: function(element, effect) { + element = $(element); + effect = (effect || 'appear').toLowerCase(); + var options = Object.extend({ + queue: { position:'end', scope:(element.id || 'global'), limit: 1 } + }, arguments[2] || { }); + Effect[element.visible() ? + Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options); + } +}; + +Effect.DefaultOptions.transition = Effect.Transitions.sinoidal; + +/* ------------- core effects ------------- */ + +Effect.ScopedQueue = Class.create(Enumerable, { + initialize: function() { + this.effects = []; + this.interval = null; + }, + _each: function(iterator) { + this.effects._each(iterator); + }, + add: function(effect) { + var timestamp = new Date().getTime(); + + var position = Object.isString(effect.options.queue) ? + effect.options.queue : effect.options.queue.position; + + switch(position) { + case 'front': + // move unstarted effects after this effect + this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) { + e.startOn += effect.finishOn; + e.finishOn += effect.finishOn; + }); + break; + case 'with-last': + timestamp = this.effects.pluck('startOn').max() || timestamp; + break; + case 'end': + // start effect after last queued effect has finished + timestamp = this.effects.pluck('finishOn').max() || timestamp; + break; + } + + effect.startOn += timestamp; + effect.finishOn += timestamp; + + if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) + this.effects.push(effect); + + if (!this.interval) + this.interval = setInterval(this.loop.bind(this), 15); + }, + remove: function(effect) { + this.effects = this.effects.reject(function(e) { return e==effect }); + if (this.effects.length == 0) { + clearInterval(this.interval); + this.interval = null; + } + }, + loop: function() { + var timePos = new Date().getTime(); + for(var i=0, len=this.effects.length;i= this.startOn) { + if (timePos >= this.finishOn) { + this.render(1.0); + this.cancel(); + this.event('beforeFinish'); + if (this.finish) this.finish(); + this.event('afterFinish'); + return; + } + var pos = (timePos - this.startOn) / this.totalTime, + frame = (pos * this.totalFrames).round(); + if (frame > this.currentFrame) { + this.render(pos); + this.currentFrame = frame; + } + } + }, + cancel: function() { + if (!this.options.sync) + Effect.Queues.get(Object.isString(this.options.queue) ? + 'global' : this.options.queue.scope).remove(this); + this.state = 'finished'; + }, + event: function(eventName) { + if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this); + if (this.options[eventName]) this.options[eventName](this); + }, + inspect: function() { + var data = $H(); + for(property in this) + if (!Object.isFunction(this[property])) data.set(property, this[property]); + return '#'; + } +}); + +Effect.Parallel = Class.create(Effect.Base, { + initialize: function(effects) { + this.effects = effects || []; + this.start(arguments[1]); + }, + update: function(position) { + this.effects.invoke('render', position); + }, + finish: function(position) { + this.effects.each( function(effect) { + effect.render(1.0); + effect.cancel(); + effect.event('beforeFinish'); + if (effect.finish) effect.finish(position); + effect.event('afterFinish'); + }); + } +}); + +Effect.Tween = Class.create(Effect.Base, { + initialize: function(object, from, to) { + object = Object.isString(object) ? $(object) : object; + var args = $A(arguments), method = args.last(), + options = args.length == 5 ? args[3] : null; + this.method = Object.isFunction(method) ? method.bind(object) : + Object.isFunction(object[method]) ? object[method].bind(object) : + function(value) { object[method] = value }; + this.start(Object.extend({ from: from, to: to }, options || { })); + }, + update: function(position) { + this.method(position); + } +}); + +Effect.Event = Class.create(Effect.Base, { + initialize: function() { + this.start(Object.extend({ duration: 0 }, arguments[0] || { })); + }, + update: Prototype.emptyFunction +}); + +Effect.Opacity = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + // make this work on IE on elements without 'layout' + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + var options = Object.extend({ + from: this.element.getOpacity() || 0.0, + to: 1.0 + }, arguments[1] || { }); + this.start(options); + }, + update: function(position) { + this.element.setOpacity(position); + } +}); + +Effect.Move = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + x: 0, + y: 0, + mode: 'relative' + }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + this.element.makePositioned(); + this.originalLeft = parseFloat(this.element.getStyle('left') || '0'); + this.originalTop = parseFloat(this.element.getStyle('top') || '0'); + if (this.options.mode == 'absolute') { + this.options.x = this.options.x - this.originalLeft; + this.options.y = this.options.y - this.originalTop; + } + }, + update: function(position) { + this.element.setStyle({ + left: (this.options.x * position + this.originalLeft).round() + 'px', + top: (this.options.y * position + this.originalTop).round() + 'px' + }); + } +}); + +// for backwards compatibility +Effect.MoveBy = function(element, toTop, toLeft) { + return new Effect.Move(element, + Object.extend({ x: toLeft, y: toTop }, arguments[3] || { })); +}; + +Effect.Scale = Class.create(Effect.Base, { + initialize: function(element, percent) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + scaleX: true, + scaleY: true, + scaleContent: true, + scaleFromCenter: false, + scaleMode: 'box', // 'box' or 'contents' or { } with provided values + scaleFrom: 100.0, + scaleTo: percent + }, arguments[2] || { }); + this.start(options); + }, + setup: function() { + this.restoreAfterFinish = this.options.restoreAfterFinish || false; + this.elementPositioning = this.element.getStyle('position'); + + this.originalStyle = { }; + ['top','left','width','height','fontSize'].each( function(k) { + this.originalStyle[k] = this.element.style[k]; + }.bind(this)); + + this.originalTop = this.element.offsetTop; + this.originalLeft = this.element.offsetLeft; + + var fontSize = this.element.getStyle('font-size') || '100%'; + ['em','px','%','pt'].each( function(fontSizeType) { + if (fontSize.indexOf(fontSizeType)>0) { + this.fontSize = parseFloat(fontSize); + this.fontSizeType = fontSizeType; + } + }.bind(this)); + + this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; + + this.dims = null; + if (this.options.scaleMode=='box') + this.dims = [this.element.offsetHeight, this.element.offsetWidth]; + if (/^content/.test(this.options.scaleMode)) + this.dims = [this.element.scrollHeight, this.element.scrollWidth]; + if (!this.dims) + this.dims = [this.options.scaleMode.originalHeight, + this.options.scaleMode.originalWidth]; + }, + update: function(position) { + var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); + if (this.options.scaleContent && this.fontSize) + this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType }); + this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); + }, + finish: function(position) { + if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle); + }, + setDimensions: function(height, width) { + var d = { }; + if (this.options.scaleX) d.width = width.round() + 'px'; + if (this.options.scaleY) d.height = height.round() + 'px'; + if (this.options.scaleFromCenter) { + var topd = (height - this.dims[0])/2; + var leftd = (width - this.dims[1])/2; + if (this.elementPositioning == 'absolute') { + if (this.options.scaleY) d.top = this.originalTop-topd + 'px'; + if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px'; + } else { + if (this.options.scaleY) d.top = -topd + 'px'; + if (this.options.scaleX) d.left = -leftd + 'px'; + } + } + this.element.setStyle(d); + } +}); + +Effect.Highlight = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { }); + this.start(options); + }, + setup: function() { + // Prevent executing on elements not in the layout flow + if (this.element.getStyle('display')=='none') { this.cancel(); return; } + // Disable background image during the effect + this.oldStyle = { }; + if (!this.options.keepBackgroundImage) { + this.oldStyle.backgroundImage = this.element.getStyle('background-image'); + this.element.setStyle({backgroundImage: 'none'}); + } + if (!this.options.endcolor) + this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff'); + if (!this.options.restorecolor) + this.options.restorecolor = this.element.getStyle('background-color'); + // init color calculations + this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this)); + this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this)); + }, + update: function(position) { + this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){ + return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) }); + }, + finish: function() { + this.element.setStyle(Object.extend(this.oldStyle, { + backgroundColor: this.options.restorecolor + })); + } +}); + +Effect.ScrollTo = function(element) { + var options = arguments[1] || { }, + scrollOffsets = document.viewport.getScrollOffsets(), + elementOffsets = $(element).cumulativeOffset(), + max = document.viewport.getScrollOffsets[0] - document.viewport.getHeight(); + + if (options.offset) elementOffsets[1] += options.offset; + + return new Effect.Tween(null, + scrollOffsets.top, + elementOffsets[1] > max ? max : elementOffsets[1], + options, + function(p){ scrollTo(scrollOffsets.left, p.round()) } + ); +}; + +/* ------------- combination effects ------------- */ + +Effect.Fade = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + var options = Object.extend({ + from: element.getOpacity() || 1.0, + to: 0.0, + afterFinishInternal: function(effect) { + if (effect.options.to!=0) return; + effect.element.hide().setStyle({opacity: oldOpacity}); + } + }, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Appear = function(element) { + element = $(element); + var options = Object.extend({ + from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0), + to: 1.0, + // force Safari to render floated elements properly + afterFinishInternal: function(effect) { + effect.element.forceRerendering(); + }, + beforeSetup: function(effect) { + effect.element.setOpacity(effect.options.from).show(); + }}, arguments[1] || { }); + return new Effect.Opacity(element,options); +}; + +Effect.Puff = function(element) { + element = $(element); + var oldStyle = { + opacity: element.getInlineOpacity(), + position: element.getStyle('position'), + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height + }; + return new Effect.Parallel( + [ new Effect.Scale(element, 200, + { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 } ) ], + Object.extend({ duration: 1.0, + beforeSetupInternal: function(effect) { + Position.absolutize(effect.effects[0].element) + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().setStyle(oldStyle); } + }, arguments[1] || { }) + ); +}; + +Effect.BlindUp = function(element) { + element = $(element); + element.makeClipping(); + return new Effect.Scale(element, 0, + Object.extend({ scaleContent: false, + scaleX: false, + restoreAfterFinish: true, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }, arguments[1] || { }) + ); +}; + +Effect.BlindDown = function(element) { + element = $(element); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: 0, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping(); + } + }, arguments[1] || { })); +}; + +Effect.SwitchOff = function(element) { + element = $(element); + var oldOpacity = element.getInlineOpacity(); + return new Effect.Appear(element, Object.extend({ + duration: 0.4, + from: 0, + transition: Effect.Transitions.flicker, + afterFinishInternal: function(effect) { + new Effect.Scale(effect.element, 1, { + duration: 0.3, scaleFromCenter: true, + scaleX: false, scaleContent: false, restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity}); + } + }) + } + }, arguments[1] || { })); +}; + +Effect.DropOut = function(element) { + element = $(element); + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left'), + opacity: element.getInlineOpacity() }; + return new Effect.Parallel( + [ new Effect.Move(element, {x: 0, y: 100, sync: true }), + new Effect.Opacity(element, { sync: true, to: 0.0 }) ], + Object.extend( + { duration: 0.5, + beforeSetup: function(effect) { + effect.effects[0].element.makePositioned(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle); + } + }, arguments[1] || { })); +}; + +Effect.Shake = function(element) { + element = $(element); + var options = Object.extend({ + distance: 20, + duration: 0.5 + }, arguments[1] || {}); + var distance = parseFloat(options.distance); + var split = parseFloat(options.duration) / 10.0; + var oldStyle = { + top: element.getStyle('top'), + left: element.getStyle('left') }; + return new Effect.Move(element, + { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) { + new Effect.Move(effect.element, + { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) { + effect.element.undoPositioned().setStyle(oldStyle); + }}) }}) }}) }}) }}) }}); +}; + +Effect.SlideDown = function(element) { + element = $(element).cleanWhitespace(); + // SlideDown need to have the content of the element wrapped in a container element with fixed height! + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, 100, Object.extend({ + scaleContent: false, + scaleX: false, + scaleFrom: window.opera ? 0 : 1, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().setStyle({height: '0px'}).show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); } + }, arguments[1] || { }) + ); +}; + +Effect.SlideUp = function(element) { + element = $(element).cleanWhitespace(); + var oldInnerBottom = element.down().getStyle('bottom'); + var elementDimensions = element.getDimensions(); + return new Effect.Scale(element, window.opera ? 0 : 1, + Object.extend({ scaleContent: false, + scaleX: false, + scaleMode: 'box', + scaleFrom: 100, + scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, + restoreAfterFinish: true, + afterSetup: function(effect) { + effect.element.makePositioned(); + effect.element.down().makePositioned(); + if (window.opera) effect.element.setStyle({top: ''}); + effect.element.makeClipping().show(); + }, + afterUpdateInternal: function(effect) { + effect.element.down().setStyle({bottom: + (effect.dims[0] - effect.element.clientHeight) + 'px' }); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().undoPositioned(); + effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); + } + }, arguments[1] || { }) + ); +}; + +// Bug in opera makes the TD containing this element expand for a instance after finish +Effect.Squish = function(element) { + return new Effect.Scale(element, window.opera ? 1 : 0, { + restoreAfterFinish: true, + beforeSetup: function(effect) { + effect.element.makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping(); + } + }); +}; + +Effect.Grow = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.full + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var initialMoveX, initialMoveY; + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + initialMoveX = initialMoveY = moveX = moveY = 0; + break; + case 'top-right': + initialMoveX = dims.width; + initialMoveY = moveY = 0; + moveX = -dims.width; + break; + case 'bottom-left': + initialMoveX = moveX = 0; + initialMoveY = dims.height; + moveY = -dims.height; + break; + case 'bottom-right': + initialMoveX = dims.width; + initialMoveY = dims.height; + moveX = -dims.width; + moveY = -dims.height; + break; + case 'center': + initialMoveX = dims.width / 2; + initialMoveY = dims.height / 2; + moveX = -dims.width / 2; + moveY = -dims.height / 2; + break; + } + + return new Effect.Move(element, { + x: initialMoveX, + y: initialMoveY, + duration: 0.01, + beforeSetup: function(effect) { + effect.element.hide().makeClipping().makePositioned(); + }, + afterFinishInternal: function(effect) { + new Effect.Parallel( + [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), + new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), + new Effect.Scale(effect.element, 100, { + scaleMode: { originalHeight: dims.height, originalWidth: dims.width }, + sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true}) + ], Object.extend({ + beforeSetup: function(effect) { + effect.effects[0].element.setStyle({height: '0px'}).show(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle); + } + }, options) + ) + } + }); +}; + +Effect.Shrink = function(element) { + element = $(element); + var options = Object.extend({ + direction: 'center', + moveTransition: Effect.Transitions.sinoidal, + scaleTransition: Effect.Transitions.sinoidal, + opacityTransition: Effect.Transitions.none + }, arguments[1] || { }); + var oldStyle = { + top: element.style.top, + left: element.style.left, + height: element.style.height, + width: element.style.width, + opacity: element.getInlineOpacity() }; + + var dims = element.getDimensions(); + var moveX, moveY; + + switch (options.direction) { + case 'top-left': + moveX = moveY = 0; + break; + case 'top-right': + moveX = dims.width; + moveY = 0; + break; + case 'bottom-left': + moveX = 0; + moveY = dims.height; + break; + case 'bottom-right': + moveX = dims.width; + moveY = dims.height; + break; + case 'center': + moveX = dims.width / 2; + moveY = dims.height / 2; + break; + } + + return new Effect.Parallel( + [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), + new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}), + new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) + ], Object.extend({ + beforeStartInternal: function(effect) { + effect.effects[0].element.makePositioned().makeClipping(); + }, + afterFinishInternal: function(effect) { + effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); } + }, options) + ); +}; + +Effect.Pulsate = function(element) { + element = $(element); + var options = arguments[1] || { }; + var oldOpacity = element.getInlineOpacity(); + var transition = options.transition || Effect.Transitions.sinoidal; + var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) }; + reverser.bind(transition); + return new Effect.Opacity(element, + Object.extend(Object.extend({ duration: 2.0, from: 0, + afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); } + }, options), {transition: reverser})); +}; + +Effect.Fold = function(element) { + element = $(element); + var oldStyle = { + top: element.style.top, + left: element.style.left, + width: element.style.width, + height: element.style.height }; + element.makeClipping(); + return new Effect.Scale(element, 5, Object.extend({ + scaleContent: false, + scaleX: false, + afterFinishInternal: function(effect) { + new Effect.Scale(element, 1, { + scaleContent: false, + scaleY: false, + afterFinishInternal: function(effect) { + effect.element.hide().undoClipping().setStyle(oldStyle); + } }); + }}, arguments[1] || { })); +}; + +Effect.Morph = Class.create(Effect.Base, { + initialize: function(element) { + this.element = $(element); + if (!this.element) throw(Effect._elementDoesNotExistError); + var options = Object.extend({ + style: { } + }, arguments[1] || { }); + + if (!Object.isString(options.style)) this.style = $H(options.style); + else { + if (options.style.include(':')) + this.style = options.style.parseStyle(); + else { + this.element.addClassName(options.style); + this.style = $H(this.element.getStyles()); + this.element.removeClassName(options.style); + var css = this.element.getStyles(); + this.style = this.style.reject(function(style) { + return style.value == css[style.key]; + }); + options.afterFinishInternal = function(effect) { + effect.element.addClassName(effect.options.style); + effect.transforms.each(function(transform) { + effect.element.style[transform.style] = ''; + }); + } + } + } + this.start(options); + }, + + setup: function(){ + function parseColor(color){ + if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff'; + color = color.parseColor(); + return $R(0,2).map(function(i){ + return parseInt( color.slice(i*2+1,i*2+3), 16 ) + }); + } + this.transforms = this.style.map(function(pair){ + var property = pair[0], value = pair[1], unit = null; + + if (value.parseColor('#zzzzzz') != '#zzzzzz') { + value = value.parseColor(); + unit = 'color'; + } else if (property == 'opacity') { + value = parseFloat(value); + if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) + this.element.setStyle({zoom: 1}); + } else if (Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } + + var originalValue = this.element.getStyle(property); + return { + style: property.camelize(), + originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), + targetValue: unit=='color' ? parseColor(value) : value, + unit: unit + }; + }.bind(this)).reject(function(transform){ + return ( + (transform.originalValue == transform.targetValue) || + ( + transform.unit != 'color' && + (isNaN(transform.originalValue) || isNaN(transform.targetValue)) + ) + ) + }); + }, + update: function(position) { + var style = { }, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : + (transform.originalValue + + (transform.targetValue - transform.originalValue) * position).toFixed(3) + + (transform.unit === null ? '' : transform.unit); + this.element.setStyle(style, true); + } +}); + +Effect.Transform = Class.create({ + initialize: function(tracks){ + this.tracks = []; + this.options = arguments[1] || { }; + this.addTracks(tracks); + }, + addTracks: function(tracks){ + tracks.each(function(track){ + track = $H(track); + var data = track.values().first(); + this.tracks.push($H({ + ids: track.keys().first(), + effect: Effect.Morph, + options: { style: data } + })); + }.bind(this)); + return this; + }, + play: function(){ + return new Effect.Parallel( + this.tracks.map(function(track){ + var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options'); + var elements = [$(ids) || $$(ids)].flatten(); + return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) }); + }).flatten(), + this.options + ); + } +}); + +Element.CSS_PROPERTIES = $w( + 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' + + 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' + + 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' + + 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' + + 'fontSize fontWeight height left letterSpacing lineHeight ' + + 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+ + 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' + + 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' + + 'right textIndent top width wordSpacing zIndex'); + +Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; + +String.__parseStyleElement = document.createElement('div'); +String.prototype.parseStyle = function(){ + var style, styleRules = $H(); + if (Prototype.Browser.WebKit) + style = new Element('div',{style:this}).style; + else { + String.__parseStyleElement.innerHTML = '
    '; + style = String.__parseStyleElement.childNodes[0].style; + } + + Element.CSS_PROPERTIES.each(function(property){ + if (style[property]) styleRules.set(property, style[property]); + }); + + if (Prototype.Browser.IE && this.include('opacity')) + styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]); + + return styleRules; +}; + +if (document.defaultView && document.defaultView.getComputedStyle) { + Element.getStyles = function(element) { + var css = document.defaultView.getComputedStyle($(element), null); + return Element.CSS_PROPERTIES.inject({ }, function(styles, property) { + styles[property] = css[property]; + return styles; + }); + }; +} else { + Element.getStyles = function(element) { + element = $(element); + var css = element.currentStyle, styles; + styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) { + results[property] = css[property]; + return results; + }); + if (!styles.opacity) styles.opacity = element.getOpacity(); + return styles; + }; +}; + +Effect.Methods = { + morph: function(element, style) { + element = $(element); + new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { })); + return element; + }, + visualEffect: function(element, effect, options) { + element = $(element) + var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1); + new Effect[klass](element, options); + return element; + }, + highlight: function(element, options) { + element = $(element); + new Effect.Highlight(element, options); + return element; + } +}; + +$w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+ + 'pulsate shake puff squish switchOff dropOut').each( + function(effect) { + Effect.Methods[effect] = function(element, options){ + element = $(element); + Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options); + return element; + } + } +); + +$w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each( + function(f) { Effect.Methods[f] = Element[f]; } +); + +Element.addMethods(Effect.Methods); diff --git a/doc/javascripts/item_index.js b/doc/javascripts/item_index.js new file mode 100644 index 000000000..6bdbdb860 --- /dev/null +++ b/doc/javascripts/item_index.js @@ -0,0 +1,458 @@ +if (!window.PDoc) window.PDoc = {}; +PDoc.elements = { + 'Element#remove': { 'name': 'Element#remove', 'type': 'instance method', 'path': 'dom/element/prototype/remove' }, +'Form.Element.serialize': { 'name': 'Form.Element.serialize', 'type': 'class method', 'path': 'dom/form/element/serialize' }, +'Hash#toTemplateReplacements': { 'name': 'Hash#toTemplateReplacements', 'type': 'instance method', 'path': 'language/hash/prototype/totemplatereplacements' }, +'Enumerable#zip': { 'name': 'Enumerable#zip', 'type': 'instance method', 'path': 'language/enumerable/prototype/zip' }, +'String': { 'name': 'String', 'type': 'class', 'path': 'language/string' }, +'Element.descendantOf': { 'name': 'Element.descendantOf', 'type': 'class method', 'path': 'dom/element/descendantof' }, +'Element#immediateDescendants': { 'name': 'Element#immediateDescendants', 'type': 'instance method', 'path': 'dom/element/prototype/immediatedescendants' }, +'String#extractScripts': { 'name': 'String#extractScripts', 'type': 'instance method', 'path': 'language/string/prototype/extractscripts' }, +'Event.Handler#start': { 'name': 'Event.Handler#start', 'type': 'instance property', 'path': 'dom/event/handler/prototype/start' }, +'Element#makePositioned': { 'name': 'Element#makePositioned', 'type': 'instance method', 'path': 'dom/element/prototype/makepositioned' }, +'Element.stopObserving': { 'name': 'Element.stopObserving', 'type': 'class method', 'path': 'dom/element/stopobserving' }, +'new Ajax.PeriodicalUpdater': { 'name': 'new Ajax.PeriodicalUpdater', 'type': 'constructor', 'path': 'ajax/ajax/periodicalupdater/new' }, +'Event': { 'name': 'Event', 'type': 'class', 'path': 'dom/event' }, +'String#blank': { 'name': 'String#blank', 'type': 'instance method', 'path': 'language/string/prototype/blank' }, +'Element#on': { 'name': 'Element#on', 'type': 'instance method', 'path': 'dom/element/prototype/on' }, +'Element#positionedOffset': { 'name': 'Element#positionedOffset', 'type': 'instance method', 'path': 'dom/element/prototype/positionedoffset' }, +'Number#round': { 'name': 'Number#round', 'type': 'instance method', 'path': 'language/number/prototype/round' }, +'Array#uniq': { 'name': 'Array#uniq', 'type': 'instance method', 'path': 'language/array/prototype/uniq' }, +'Template#evaluate': { 'name': 'Template#evaluate', 'type': 'instance method', 'path': 'language/template/prototype/evaluate' }, +'Form.Element#getValue': { 'name': 'Form.Element#getValue', 'type': 'instance method', 'path': 'dom/form/element/prototype/getvalue' }, +'Event.pointerX': { 'name': 'Event.pointerX', 'type': 'class method', 'path': 'dom/event/pointerx' }, +'Element.getHeight': { 'name': 'Element.getHeight', 'type': 'class method', 'path': 'dom/element/getheight' }, +'Form.request': { 'name': 'Form.request', 'type': 'class method', 'path': 'dom/form/request' }, +'Array': { 'name': 'Array', 'type': 'class', 'path': 'language/array' }, +'Try': { 'name': 'Try', 'type': 'namespace', 'path': 'language/try' }, +'Event.pointerY': { 'name': 'Event.pointerY', 'type': 'class method', 'path': 'dom/event/pointery' }, +'Element.select': { 'name': 'Element.select', 'type': 'class method', 'path': 'dom/element/select' }, +'$A': { 'name': '$A', 'type': 'utility', 'path': 'language/dollara' }, +'Number#floor': { 'name': 'Number#floor', 'type': 'instance method', 'path': 'language/number/prototype/floor' }, +'Element#getOffsetParent': { 'name': 'Element#getOffsetParent', 'type': 'instance method', 'path': 'dom/element/prototype/getoffsetparent' }, +'ObjectRange': { 'name': 'ObjectRange', 'type': 'class', 'path': 'language/objectrange' }, +'new Element': { 'name': 'new Element', 'type': 'constructor', 'path': 'dom/element/new' }, +'String#empty': { 'name': 'String#empty', 'type': 'instance method', 'path': 'language/string/prototype/empty' }, +'Element.hasClassName': { 'name': 'Element.hasClassName', 'type': 'class method', 'path': 'dom/element/hasclassname' }, +'Element.Offset#toArray': { 'name': 'Element.Offset#toArray', 'type': 'instance method', 'path': 'dom/element/offset/prototype/toarray' }, +'Event.pointer': { 'name': 'Event.pointer', 'type': 'class method', 'path': 'dom/event/pointer' }, +'Element#setOpacity': { 'name': 'Element#setOpacity', 'type': 'instance method', 'path': 'dom/element/prototype/setopacity' }, +'Object.isHash': { 'name': 'Object.isHash', 'type': 'class method', 'path': 'language/object/ishash' }, +'Ajax.Response#request': { 'name': 'Ajax.Response#request', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/request' }, +'Event.extend': { 'name': 'Event.extend', 'type': 'class method', 'path': 'dom/event/extend' }, +'Prototype.Selector': { 'name': 'Prototype.Selector', 'type': 'namespace', 'path': 'language/prototype/selector' }, +'String.interpret': { 'name': 'String.interpret', 'type': 'class method', 'path': 'language/string/interpret' }, +'Element.viewportOffset': { 'name': 'Element.viewportOffset', 'type': 'class method', 'path': 'dom/element/viewportoffset' }, +'String#scan': { 'name': 'String#scan', 'type': 'instance method', 'path': 'language/string/prototype/scan' }, +'Event#element': { 'name': 'Event#element', 'type': 'instance method', 'path': 'dom/event/prototype/element' }, +'document.fire': { 'name': 'document.fire', 'type': 'class method', 'path': 'dom/document/fire' }, +'Object.toQueryString': { 'name': 'Object.toQueryString', 'type': 'class method', 'path': 'language/object/toquerystring' }, +'Element#hide': { 'name': 'Element#hide', 'type': 'instance method', 'path': 'dom/element/prototype/hide' }, +'$F': { 'name': '$F', 'type': 'utility', 'path': 'dom/dollarf' }, +'Hash#toQueryString': { 'name': 'Hash#toQueryString', 'type': 'instance method', 'path': 'language/hash/prototype/toquerystring' }, +'Ajax.Responders.register': { 'name': 'Ajax.Responders.register', 'type': 'class method', 'path': 'ajax/ajax/responders/register' }, +'Hash#merge': { 'name': 'Hash#merge', 'type': 'instance method', 'path': 'language/hash/prototype/merge' }, +'Enumerable#grep': { 'name': 'Enumerable#grep', 'type': 'instance method', 'path': 'language/enumerable/prototype/grep' }, +'RegExp#match': { 'name': 'RegExp#match', 'type': 'instance method', 'path': 'language/regexp/prototype/match' }, +'Object.toHTML': { 'name': 'Object.toHTML', 'type': 'class method', 'path': 'language/object/tohtml' }, +'Element.recursivelyCollect': { 'name': 'Element.recursivelyCollect', 'type': 'class method', 'path': 'dom/element/recursivelycollect' }, +'Element.adjacent': { 'name': 'Element.adjacent', 'type': 'class method', 'path': 'dom/element/adjacent' }, +'Element.next': { 'name': 'Element.next', 'type': 'class method', 'path': 'dom/element/next' }, +'$H': { 'name': '$H', 'type': 'utility', 'path': 'language/dollarh' }, +'Element#getHeight': { 'name': 'Element#getHeight', 'type': 'instance method', 'path': 'dom/element/prototype/getheight' }, +'Element#recursivelyCollect': { 'name': 'Element#recursivelyCollect', 'type': 'instance method', 'path': 'dom/element/prototype/recursivelycollect' }, +'String#toQueryParams': { 'name': 'String#toQueryParams', 'type': 'instance method', 'path': 'language/string/prototype/toqueryparams' }, +'Element.getStorage': { 'name': 'Element.getStorage', 'type': 'class method', 'path': 'dom/element/getstorage' }, +'Element.insert': { 'name': 'Element.insert', 'type': 'class method', 'path': 'dom/element/insert' }, +'new Element.Layout': { 'name': 'new Element.Layout', 'type': 'constructor', 'path': 'dom/element/layout/new' }, +'Enumerable#invoke': { 'name': 'Enumerable#invoke', 'type': 'instance method', 'path': 'language/enumerable/prototype/invoke' }, +'Element.addMethods': { 'name': 'Element.addMethods', 'type': 'class method', 'path': 'dom/element/addmethods' }, +'Element#setStyle': { 'name': 'Element#setStyle', 'type': 'instance method', 'path': 'dom/element/prototype/setstyle' }, +'Array#last': { 'name': 'Array#last', 'type': 'instance method', 'path': 'language/array/prototype/last' }, +'Element#show': { 'name': 'Element#show', 'type': 'instance method', 'path': 'dom/element/prototype/show' }, +'Event.Handler': { 'name': 'Event.Handler', 'type': 'class', 'path': 'dom/event/handler' }, +'Function#bind': { 'name': 'Function#bind', 'type': 'instance method', 'path': 'language/function/prototype/bind' }, +'Element.observe': { 'name': 'Element.observe', 'type': 'class method', 'path': 'dom/element/observe' }, +'document.viewport.getScrollOffsets': { 'name': 'document.viewport.getScrollOffsets', 'type': 'class method', 'path': 'dom/document/viewport/getscrolloffsets' }, +'String#unfilterJSON': { 'name': 'String#unfilterJSON', 'type': 'instance method', 'path': 'language/string/prototype/unfilterjson' }, +'Hash#index': { 'name': 'Hash#index', 'type': 'instance method', 'path': 'language/hash/prototype/index' }, +'Array#clear': { 'name': 'Array#clear', 'type': 'instance method', 'path': 'language/array/prototype/clear' }, +'Form.Element.getValue': { 'name': 'Form.Element.getValue', 'type': 'class method', 'path': 'dom/form/element/getvalue' }, +'Element.absolutize': { 'name': 'Element.absolutize', 'type': 'class method', 'path': 'dom/element/absolutize' }, +'Array.from': { 'name': 'Array.from', 'type': 'class method', 'path': 'language/array/from' }, +'Element.update': { 'name': 'Element.update', 'type': 'class method', 'path': 'dom/element/update' }, +'Ajax.Response#responseXML': { 'name': 'Ajax.Response#responseXML', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsexml' }, +'Form.Element#serialize': { 'name': 'Form.Element#serialize', 'type': 'instance method', 'path': 'dom/form/element/prototype/serialize' }, +'$R': { 'name': '$R', 'type': 'utility', 'path': 'language/dollarr' }, +'Form.Element.present': { 'name': 'Form.Element.present', 'type': 'class method', 'path': 'dom/form/element/present' }, +'Element.clone': { 'name': 'Element.clone', 'type': 'class method', 'path': 'dom/element/clone' }, +'Element#writeAttribute': { 'name': 'Element#writeAttribute', 'type': 'instance method', 'path': 'dom/element/prototype/writeattribute' }, +'Enumerable#inject': { 'name': 'Enumerable#inject', 'type': 'instance method', 'path': 'language/enumerable/prototype/inject' }, +'Element.visible': { 'name': 'Element.visible', 'type': 'class method', 'path': 'dom/element/visible' }, +'Element#next': { 'name': 'Element#next', 'type': 'instance method', 'path': 'dom/element/prototype/next' }, +'Element#previous': { 'name': 'Element#previous', 'type': 'instance method', 'path': 'dom/element/prototype/previous' }, +'Element': { 'name': 'Element', 'type': 'class', 'path': 'dom/element' }, +'Element.Layout.COMPOSITE_PROPERTIES': { 'name': 'Element.Layout.COMPOSITE_PROPERTIES', 'type': 'constant', 'path': 'dom/element/layout/composite_properties' }, +'new Selector': { 'name': 'new Selector', 'type': 'constructor', 'path': 'dom/selector/new' }, +'Element#descendants': { 'name': 'Element#descendants', 'type': 'instance method', 'path': 'dom/element/prototype/descendants' }, +'Object': { 'name': 'Object', 'type': 'class', 'path': 'language/object' }, +'Enumerable#include': { 'name': 'Enumerable#include', 'type': 'instance method', 'path': 'language/enumerable/prototype/include' }, +'String#dasherize': { 'name': 'String#dasherize', 'type': 'instance method', 'path': 'language/string/prototype/dasherize' }, +'Element#replace': { 'name': 'Element#replace', 'type': 'instance method', 'path': 'dom/element/prototype/replace' }, +'Element#toggle': { 'name': 'Element#toggle', 'type': 'instance method', 'path': 'dom/element/prototype/toggle' }, +'String#interpolate': { 'name': 'String#interpolate', 'type': 'instance method', 'path': 'language/string/prototype/interpolate' }, +'String#camelize': { 'name': 'String#camelize', 'type': 'instance method', 'path': 'language/string/prototype/camelize' }, +'new ObjectRange': { 'name': 'new ObjectRange', 'type': 'constructor', 'path': 'language/objectrange/new' }, +'Object.isElement': { 'name': 'Object.isElement', 'type': 'class method', 'path': 'language/object/iselement' }, +'Element#relativize': { 'name': 'Element#relativize', 'type': 'instance method', 'path': 'dom/element/prototype/relativize' }, +'String#unescapeHTML': { 'name': 'String#unescapeHTML', 'type': 'instance method', 'path': 'language/string/prototype/unescapehtml' }, +'Array#flatten': { 'name': 'Array#flatten', 'type': 'instance method', 'path': 'language/array/prototype/flatten' }, +'Prototype.BrowserFeatures.SelectorsAPI': { 'name': 'Prototype.BrowserFeatures.SelectorsAPI', 'type': 'class property', 'path': 'language/prototype/browserfeatures/selectorsapi' }, +'Element.makePositioned': { 'name': 'Element.makePositioned', 'type': 'class method', 'path': 'dom/element/makepositioned' }, +'Event#isMiddleClick': { 'name': 'Event#isMiddleClick', 'type': 'instance method', 'path': 'dom/event/prototype/ismiddleclick' }, +'document': { 'name': 'document', 'type': 'namespace', 'path': 'dom/document' }, +'String#times': { 'name': 'String#times', 'type': 'instance method', 'path': 'language/string/prototype/times' }, +'Abstract.EventObserver': { 'name': 'Abstract.EventObserver', 'type': 'class', 'path': 'dom/abstract/eventobserver' }, +'Event.findElement': { 'name': 'Event.findElement', 'type': 'class method', 'path': 'dom/event/findelement' }, +'Element.positionedOffset': { 'name': 'Element.positionedOffset', 'type': 'class method', 'path': 'dom/element/positionedoffset' }, +'Form#reset': { 'name': 'Form#reset', 'type': 'instance method', 'path': 'dom/form/prototype/reset' }, +'$': { 'name': '$', 'type': 'utility', 'path': 'dom/dollar' }, +'Abstract.TimedObserver': { 'name': 'Abstract.TimedObserver', 'type': 'class', 'path': 'dom/abstract/timedobserver' }, +'Hash#get': { 'name': 'Hash#get', 'type': 'instance method', 'path': 'language/hash/prototype/get' }, +'Number': { 'name': 'Number', 'type': 'class', 'path': 'language/number' }, +'Element.firstDescendant': { 'name': 'Element.firstDescendant', 'type': 'class method', 'path': 'dom/element/firstdescendant' }, +'document.viewport.getDimensions': { 'name': 'document.viewport.getDimensions', 'type': 'class method', 'path': 'dom/document/viewport/getdimensions' }, +'Ajax.Response#statusText': { 'name': 'Ajax.Response#statusText', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/statustext' }, +'Element.remove': { 'name': 'Element.remove', 'type': 'class method', 'path': 'dom/element/remove' }, +'Element.setStyle': { 'name': 'Element.setStyle', 'type': 'class method', 'path': 'dom/element/setstyle' }, +'new Form.Observer': { 'name': 'new Form.Observer', 'type': 'constructor', 'path': 'dom/form/observer/new' }, +'Element.up': { 'name': 'Element.up', 'type': 'class method', 'path': 'dom/element/up' }, +'Element.hide': { 'name': 'Element.hide', 'type': 'class method', 'path': 'dom/element/hide' }, +'Function': { 'name': 'Function', 'type': 'class', 'path': 'language/function' }, +'Event.isMiddleClick': { 'name': 'Event.isMiddleClick', 'type': 'class method', 'path': 'dom/event/ismiddleclick' }, +'Event.Handler#stop': { 'name': 'Event.Handler#stop', 'type': 'instance property', 'path': 'dom/event/handler/prototype/stop' }, +'Number#ceil': { 'name': 'Number#ceil', 'type': 'instance method', 'path': 'language/number/prototype/ceil' }, +'Form.Element#setValue': { 'name': 'Form.Element#setValue', 'type': 'instance method', 'path': 'dom/form/element/prototype/setvalue' }, +'Element.getStyle': { 'name': 'Element.getStyle', 'type': 'class method', 'path': 'dom/element/getstyle' }, +'Element#down': { 'name': 'Element#down', 'type': 'instance method', 'path': 'dom/element/prototype/down' }, +'Element.show': { 'name': 'Element.show', 'type': 'class method', 'path': 'dom/element/show' }, +'Element.Layout#toCSS': { 'name': 'Element.Layout#toCSS', 'type': 'instance method', 'path': 'dom/element/layout/prototype/tocss' }, +'ObjectRange#end': { 'name': 'ObjectRange#end', 'type': 'instance property', 'path': 'language/objectrange/prototype/end' }, +'Element#cumulativeScrollOffset': { 'name': 'Element#cumulativeScrollOffset', 'type': 'instance method', 'path': 'dom/element/prototype/cumulativescrolloffset' }, +'Form.getElements': { 'name': 'Form.getElements', 'type': 'class method', 'path': 'dom/form/getelements' }, +'Element.writeAttribute': { 'name': 'Element.writeAttribute', 'type': 'class method', 'path': 'dom/element/writeattribute' }, +'Element.cleanWhitespace': { 'name': 'Element.cleanWhitespace', 'type': 'class method', 'path': 'dom/element/cleanwhitespace' }, +'Form#request': { 'name': 'Form#request', 'type': 'instance method', 'path': 'dom/form/prototype/request' }, +'Date': { 'name': 'Date', 'type': 'class', 'path': 'language/date' }, +'Array#clone': { 'name': 'Array#clone', 'type': 'instance method', 'path': 'language/array/prototype/clone' }, +'Element.inspect': { 'name': 'Element.inspect', 'type': 'class method', 'path': 'dom/element/inspect' }, +'Ajax.Response#getAllResponseHeaders': { 'name': 'Ajax.Response#getAllResponseHeaders', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getallresponseheaders' }, +'Event#isLeftClick': { 'name': 'Event#isLeftClick', 'type': 'instance method', 'path': 'dom/event/prototype/isleftclick' }, +'Element.previous': { 'name': 'Element.previous', 'type': 'class method', 'path': 'dom/element/previous' }, +'Element#descendantOf': { 'name': 'Element#descendantOf', 'type': 'instance method', 'path': 'dom/element/prototype/descendantof' }, +'Selector#findElements': { 'name': 'Selector#findElements', 'type': 'instance method', 'path': 'dom/selector/prototype/findelements' }, +'Element#getWidth': { 'name': 'Element#getWidth', 'type': 'instance method', 'path': 'dom/element/prototype/getwidth' }, +'Element#getLayout': { 'name': 'Element#getLayout', 'type': 'instance method', 'path': 'dom/element/prototype/getlayout' }, +'new PeriodicalExecuter': { 'name': 'new PeriodicalExecuter', 'type': 'constructor', 'path': 'language/periodicalexecuter/new' }, +'Template': { 'name': 'Template', 'type': 'class', 'path': 'language/template' }, +'String#capitalize': { 'name': 'String#capitalize', 'type': 'instance method', 'path': 'language/string/prototype/capitalize' }, +'Element#getElementsBySelector': { 'name': 'Element#getElementsBySelector', 'type': 'instance method', 'path': 'dom/element/prototype/getelementsbyselector' }, +'Enumerable#select': { 'name': 'Enumerable#select', 'type': 'instance method', 'path': 'language/enumerable/prototype/select' }, +'Event#pointer': { 'name': 'Event#pointer', 'type': 'instance method', 'path': 'dom/event/prototype/pointer' }, +'Prototype': { 'name': 'Prototype', 'type': 'namespace', 'path': 'language/prototype' }, +'RegExp.escape': { 'name': 'RegExp.escape', 'type': 'class method', 'path': 'language/regexp/escape' }, +'Hash#clone': { 'name': 'Hash#clone', 'type': 'instance method', 'path': 'language/hash/prototype/clone' }, +'Element#cumulativeOffset': { 'name': 'Element#cumulativeOffset', 'type': 'instance method', 'path': 'dom/element/prototype/cumulativeoffset' }, +'Element#getOpacity': { 'name': 'Element#getOpacity', 'type': 'instance method', 'path': 'dom/element/prototype/getopacity' }, +'Hash#inspect': { 'name': 'Hash#inspect', 'type': 'instance method', 'path': 'language/hash/prototype/inspect' }, +'Event.fire': { 'name': 'Event.fire', 'type': 'class method', 'path': 'dom/event/fire' }, +'Element.extend': { 'name': 'Element.extend', 'type': 'class method', 'path': 'dom/element/extend' }, +'Form.Element.focus': { 'name': 'Form.Element.focus', 'type': 'class method', 'path': 'dom/form/element/focus' }, +'Ajax.PeriodicalUpdater#start': { 'name': 'Ajax.PeriodicalUpdater#start', 'type': 'instance method', 'path': 'ajax/ajax/periodicalupdater/prototype/start' }, +'Element.getElementsBySelector': { 'name': 'Element.getElementsBySelector', 'type': 'class method', 'path': 'dom/element/getelementsbyselector' }, +'Element#makeClipping': { 'name': 'Element#makeClipping', 'type': 'instance method', 'path': 'dom/element/prototype/makeclipping' }, +'Element.makeClipping': { 'name': 'Element.makeClipping', 'type': 'class method', 'path': 'dom/element/makeclipping' }, +'Abstract': { 'name': 'Abstract', 'type': 'namespace', 'path': 'dom/abstract' }, +'Element.addClassName': { 'name': 'Element.addClassName', 'type': 'class method', 'path': 'dom/element/addclassname' }, +'Element.removeClassName': { 'name': 'Element.removeClassName', 'type': 'class method', 'path': 'dom/element/removeclassname' }, +'Form.Element.clear': { 'name': 'Form.Element.clear', 'type': 'class method', 'path': 'dom/form/element/clear' }, +'Element.setOpacity': { 'name': 'Element.setOpacity', 'type': 'class method', 'path': 'dom/element/setopacity' }, +'String#truncate': { 'name': 'String#truncate', 'type': 'instance method', 'path': 'language/string/prototype/truncate' }, +'Form.disable': { 'name': 'Form.disable', 'type': 'class method', 'path': 'dom/form/disable' }, +'Element#hasClassName': { 'name': 'Element#hasClassName', 'type': 'instance method', 'path': 'dom/element/prototype/hasclassname' }, +'Ajax.Response#getHeader': { 'name': 'Ajax.Response#getHeader', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getheader' }, +'Element#fire': { 'name': 'Element#fire', 'type': 'instance method', 'path': 'dom/element/prototype/fire' }, +'Number#toColorPart': { 'name': 'Number#toColorPart', 'type': 'instance method', 'path': 'language/number/prototype/tocolorpart' }, +'Selector.findChildElements': { 'name': 'Selector.findChildElements', 'type': 'class method', 'path': 'dom/selector/findchildelements' }, +'Element#firstDescendant': { 'name': 'Element#firstDescendant', 'type': 'instance method', 'path': 'dom/element/prototype/firstdescendant' }, +'Form.Element.disable': { 'name': 'Form.Element.disable', 'type': 'class method', 'path': 'dom/form/element/disable' }, +'Element.Methods': { 'name': 'Element.Methods', 'type': 'mixin', 'path': 'dom/element/methods' }, +'String#evalJSON': { 'name': 'String#evalJSON', 'type': 'instance method', 'path': 'language/string/prototype/evaljson' }, +'String#succ': { 'name': 'String#succ', 'type': 'instance method', 'path': 'language/string/prototype/succ' }, +'Form.Element.setValue': { 'name': 'Form.Element.setValue', 'type': 'class method', 'path': 'dom/form/element/setvalue' }, +'Ajax.Request#success': { 'name': 'Ajax.Request#success', 'type': 'instance method', 'path': 'ajax/ajax/request/prototype/success' }, +'Ajax.PeriodicalUpdater#stop': { 'name': 'Ajax.PeriodicalUpdater#stop', 'type': 'instance method', 'path': 'ajax/ajax/periodicalupdater/prototype/stop' }, +'Element#select': { 'name': 'Element#select', 'type': 'instance method', 'path': 'dom/element/prototype/select' }, +'PeriodicalExecuter': { 'name': 'PeriodicalExecuter', 'type': 'class', 'path': 'language/periodicalexecuter' }, +'Prototype.BrowserFeatures.XPath': { 'name': 'Prototype.BrowserFeatures.XPath', 'type': 'class property', 'path': 'language/prototype/browserfeatures/xpath' }, +'Element#removeClassName': { 'name': 'Element#removeClassName', 'type': 'instance method', 'path': 'dom/element/prototype/removeclassname' }, +'Element#getDimensions': { 'name': 'Element#getDimensions', 'type': 'instance method', 'path': 'dom/element/prototype/getdimensions' }, +'Element#observe': { 'name': 'Element#observe', 'type': 'instance method', 'path': 'dom/element/prototype/observe' }, +'Element#up': { 'name': 'Element#up', 'type': 'instance method', 'path': 'dom/element/prototype/up' }, +'Ajax.Updater': { 'name': 'Ajax.Updater', 'type': 'class', 'path': 'ajax/ajax/updater' }, +'Prototype.Version': { 'name': 'Prototype.Version', 'type': 'class property', 'path': 'language/prototype/version' }, +'String#underscore': { 'name': 'String#underscore', 'type': 'instance method', 'path': 'language/string/prototype/underscore' }, +'String#evalScripts': { 'name': 'String#evalScripts', 'type': 'instance method', 'path': 'language/string/prototype/evalscripts' }, +'Array#indexOf': { 'name': 'Array#indexOf', 'type': 'instance method', 'path': 'language/array/prototype/indexof' }, +'Event.isRightClick': { 'name': 'Event.isRightClick', 'type': 'class method', 'path': 'dom/event/isrightclick' }, +'Form#findFirstElement': { 'name': 'Form#findFirstElement', 'type': 'instance method', 'path': 'dom/form/prototype/findfirstelement' }, +'Element#clone': { 'name': 'Element#clone', 'type': 'instance method', 'path': 'dom/element/prototype/clone' }, +'$w': { 'name': '$w', 'type': 'utility', 'path': 'language/dollarw' }, +'Class': { 'name': 'Class', 'type': 'class', 'path': 'language/class' }, +'Event.stopObserving': { 'name': 'Event.stopObserving', 'type': 'class method', 'path': 'dom/event/stopobserving' }, +'Form.enable': { 'name': 'Form.enable', 'type': 'class method', 'path': 'dom/form/enable' }, +'Array#first': { 'name': 'Array#first', 'type': 'instance method', 'path': 'language/array/prototype/first' }, +'Element.relativize': { 'name': 'Element.relativize', 'type': 'class method', 'path': 'dom/element/relativize' }, +'Enumerable#toArray': { 'name': 'Enumerable#toArray', 'type': 'instance method', 'path': 'language/enumerable/prototype/toarray' }, +'Hash#unset': { 'name': 'Hash#unset', 'type': 'instance method', 'path': 'language/hash/prototype/unset' }, +'Form.getInputs': { 'name': 'Form.getInputs', 'type': 'class method', 'path': 'dom/form/getinputs' }, +'Element#undoPositioned': { 'name': 'Element#undoPositioned', 'type': 'instance method', 'path': 'dom/element/prototype/undopositioned' }, +'Element#cleanWhitespace': { 'name': 'Element#cleanWhitespace', 'type': 'instance method', 'path': 'dom/element/prototype/cleanwhitespace' }, +'Prototype.Browser': { 'name': 'Prototype.Browser', 'type': 'namespace', 'path': 'language/prototype/browser' }, +'String#startsWith': { 'name': 'String#startsWith', 'type': 'instance method', 'path': 'language/string/prototype/startswith' }, +'Form.Element#present': { 'name': 'Form.Element#present', 'type': 'instance method', 'path': 'dom/form/element/prototype/present' }, +'Form.Element': { 'name': 'Form.Element', 'type': 'namespace', 'path': 'dom/form/element' }, +'Element.ancestors': { 'name': 'Element.ancestors', 'type': 'class method', 'path': 'dom/element/ancestors' }, +'Array#compact': { 'name': 'Array#compact', 'type': 'instance method', 'path': 'language/array/prototype/compact' }, +'String#endsWith': { 'name': 'String#endsWith', 'type': 'instance method', 'path': 'language/string/prototype/endswith' }, +'Element.classNames': { 'name': 'Element.classNames', 'type': 'class method', 'path': 'dom/element/classnames' }, +'Element#visible': { 'name': 'Element#visible', 'type': 'instance method', 'path': 'dom/element/prototype/visible' }, +'Class.create': { 'name': 'Class.create', 'type': 'class method', 'path': 'language/class/create' }, +'Element.down': { 'name': 'Element.down', 'type': 'class method', 'path': 'dom/element/down' }, +'Number#abs': { 'name': 'Number#abs', 'type': 'instance method', 'path': 'language/number/prototype/abs' }, +'String#include': { 'name': 'String#include', 'type': 'instance method', 'path': 'language/string/prototype/include' }, +'Enumerable#any': { 'name': 'Enumerable#any', 'type': 'instance method', 'path': 'language/enumerable/prototype/any' }, +'Element.toggle': { 'name': 'Element.toggle', 'type': 'class method', 'path': 'dom/element/toggle' }, +'Prototype.Selector.select': { 'name': 'Prototype.Selector.select', 'type': 'class method', 'path': 'language/prototype/selector/select' }, +'Enumerable#pluck': { 'name': 'Enumerable#pluck', 'type': 'instance method', 'path': 'language/enumerable/prototype/pluck' }, +'Form.Element.EventObserver': { 'name': 'Form.Element.EventObserver', 'type': 'class', 'path': 'dom/form/element/eventobserver' }, +'Element.getDimensions': { 'name': 'Element.getDimensions', 'type': 'class method', 'path': 'dom/element/getdimensions' }, +'Enumerable#collect': { 'name': 'Enumerable#collect', 'type': 'instance method', 'path': 'language/enumerable/prototype/collect' }, +'Form.Element.Observer': { 'name': 'Form.Element.Observer', 'type': 'class', 'path': 'dom/form/element/observer' }, +'String#gsub': { 'name': 'String#gsub', 'type': 'instance method', 'path': 'language/string/prototype/gsub' }, +'RegExp': { 'name': 'RegExp', 'type': 'class', 'path': 'language/regexp' }, +'Element#wrap': { 'name': 'Element#wrap', 'type': 'instance method', 'path': 'dom/element/prototype/wrap' }, +'Event.on': { 'name': 'Event.on', 'type': 'class method', 'path': 'dom/event/on' }, +'Ajax.Request': { 'name': 'Ajax.Request', 'type': 'class', 'path': 'ajax/ajax/request' }, +'Enumerable#inspect': { 'name': 'Enumerable#inspect', 'type': 'instance method', 'path': 'language/enumerable/prototype/inspect' }, +'Form.Element#enable': { 'name': 'Form.Element#enable', 'type': 'instance method', 'path': 'dom/form/element/prototype/enable' }, +'Object.isNumber': { 'name': 'Object.isNumber', 'type': 'class method', 'path': 'language/object/isnumber' }, +'document.stopObserving': { 'name': 'document.stopObserving', 'type': 'class method', 'path': 'dom/document/stopobserving' }, +'Element.Layout': { 'name': 'Element.Layout', 'type': 'class', 'path': 'dom/element/layout' }, +'String#strip': { 'name': 'String#strip', 'type': 'instance method', 'path': 'language/string/prototype/strip' }, +'new Element.Offset': { 'name': 'new Element.Offset', 'type': 'constructor', 'path': 'dom/element/offset/new' }, +'Element.toggleClassName': { 'name': 'Element.toggleClassName', 'type': 'class method', 'path': 'dom/element/toggleclassname' }, +'Event#findElement': { 'name': 'Event#findElement', 'type': 'instance method', 'path': 'dom/event/prototype/findelement' }, +'Element.match': { 'name': 'Element.match', 'type': 'class method', 'path': 'dom/element/match' }, +'Event#stop': { 'name': 'Event#stop', 'type': 'instance method', 'path': 'dom/event/prototype/stop' }, +'Form.serialize': { 'name': 'Form.serialize', 'type': 'class method', 'path': 'dom/form/serialize' }, +'Object.clone': { 'name': 'Object.clone', 'type': 'class method', 'path': 'language/object/clone' }, +'Object.isString': { 'name': 'Object.isString', 'type': 'class method', 'path': 'language/object/isstring' }, +'Enumerable#entries': { 'name': 'Enumerable#entries', 'type': 'instance method', 'path': 'language/enumerable/prototype/entries' }, +'Element#siblings': { 'name': 'Element#siblings', 'type': 'instance method', 'path': 'dom/element/prototype/siblings' }, +'Enumerable#member': { 'name': 'Enumerable#member', 'type': 'instance method', 'path': 'language/enumerable/prototype/member' }, +'Element.readAttribute': { 'name': 'Element.readAttribute', 'type': 'class method', 'path': 'dom/element/readattribute' }, +'Ajax.Responders.unregister': { 'name': 'Ajax.Responders.unregister', 'type': 'class method', 'path': 'ajax/ajax/responders/unregister' }, +'Element#addClassName': { 'name': 'Element#addClassName', 'type': 'instance method', 'path': 'dom/element/prototype/addclassname' }, +'String#stripScripts': { 'name': 'String#stripScripts', 'type': 'instance method', 'path': 'language/string/prototype/stripscripts' }, +'Enumerable': { 'name': 'Enumerable', 'type': 'mixin', 'path': 'language/enumerable' }, +'Element.Layout.PROPERTIES': { 'name': 'Element.Layout.PROPERTIES', 'type': 'constant', 'path': 'dom/element/layout/properties' }, +'Selector': { 'name': 'Selector', 'type': 'class', 'path': 'dom/selector' }, +'Enumerable#detect': { 'name': 'Enumerable#detect', 'type': 'instance method', 'path': 'language/enumerable/prototype/detect' }, +'Form.findFirstElement': { 'name': 'Form.findFirstElement', 'type': 'class method', 'path': 'dom/form/findfirstelement' }, +'Ajax section': { 'name': 'Ajax section', 'type': 'section', 'path': 'ajax' }, +'new Event.Handler': { 'name': 'new Event.Handler', 'type': 'constructor', 'path': 'dom/event/handler/new' }, +'Enumerable#every': { 'name': 'Enumerable#every', 'type': 'instance method', 'path': 'language/enumerable/prototype/every' }, +'Prototype.Selector.match': { 'name': 'Prototype.Selector.match', 'type': 'class method', 'path': 'language/prototype/selector/match' }, +'Enumerable#all': { 'name': 'Enumerable#all', 'type': 'instance method', 'path': 'language/enumerable/prototype/all' }, +'Element.store': { 'name': 'Element.store', 'type': 'class method', 'path': 'dom/element/store' }, +'Language section': { 'name': 'Language section', 'type': 'section', 'path': 'language' }, +'String#sub': { 'name': 'String#sub', 'type': 'instance method', 'path': 'language/string/prototype/sub' }, +'Element.Layout#get': { 'name': 'Element.Layout#get', 'type': 'instance method', 'path': 'dom/element/layout/prototype/get' }, +'Element.getWidth': { 'name': 'Element.getWidth', 'type': 'class method', 'path': 'dom/element/getwidth' }, +'Enumerable#sortBy': { 'name': 'Enumerable#sortBy', 'type': 'instance method', 'path': 'language/enumerable/prototype/sortby' }, +'Element.measure': { 'name': 'Element.measure', 'type': 'class method', 'path': 'dom/element/measure' }, +'Function#delay': { 'name': 'Function#delay', 'type': 'instance method', 'path': 'language/function/prototype/delay' }, +'Element.cumulativeScrollOffset': { 'name': 'Element.cumulativeScrollOffset', 'type': 'class method', 'path': 'dom/element/cumulativescrolloffset' }, +'Element.cumulativeOffset': { 'name': 'Element.cumulativeOffset', 'type': 'class method', 'path': 'dom/element/cumulativeoffset' }, +'Event.observe': { 'name': 'Event.observe', 'type': 'class method', 'path': 'dom/event/observe' }, +'Ajax.Responders': { 'name': 'Ajax.Responders', 'type': 'namespace', 'path': 'ajax/ajax/responders' }, +'Enumerable#find': { 'name': 'Enumerable#find', 'type': 'instance method', 'path': 'language/enumerable/prototype/find' }, +'Array#inspect': { 'name': 'Array#inspect', 'type': 'instance method', 'path': 'language/array/prototype/inspect' }, +'Enumerable#map': { 'name': 'Enumerable#map', 'type': 'instance method', 'path': 'language/enumerable/prototype/map' }, +'Element.fire': { 'name': 'Element.fire', 'type': 'class method', 'path': 'dom/element/fire' }, +'Element.getOpacity': { 'name': 'Element.getOpacity', 'type': 'class method', 'path': 'dom/element/getopacity' }, +'Form#getElements': { 'name': 'Form#getElements', 'type': 'instance method', 'path': 'dom/form/prototype/getelements' }, +'Form#serialize': { 'name': 'Form#serialize', 'type': 'instance method', 'path': 'dom/form/prototype/serialize' }, +'Element.undoPositioned': { 'name': 'Element.undoPositioned', 'type': 'class method', 'path': 'dom/element/undopositioned' }, +'Element#inspect': { 'name': 'Element#inspect', 'type': 'instance method', 'path': 'dom/element/prototype/inspect' }, +'Form.EventObserver': { 'name': 'Form.EventObserver', 'type': 'class', 'path': 'dom/form/eventobserver' }, +'Element#retrieve': { 'name': 'Element#retrieve', 'type': 'instance method', 'path': 'dom/element/prototype/retrieve' }, +'Element.empty': { 'name': 'Element.empty', 'type': 'class method', 'path': 'dom/element/empty' }, +'Element.Offset': { 'name': 'Element.Offset', 'type': 'class', 'path': 'dom/element/offset' }, +'Element.nextSiblings': { 'name': 'Element.nextSiblings', 'type': 'class method', 'path': 'dom/element/nextsiblings' }, +'Prototype.K': { 'name': 'Prototype.K', 'type': 'class method', 'path': 'language/prototype/k' }, +'String#escapeHTML': { 'name': 'String#escapeHTML', 'type': 'instance method', 'path': 'language/string/prototype/escapehtml' }, +'Object.values': { 'name': 'Object.values', 'type': 'class method', 'path': 'language/object/values' }, +'Enumerable#max': { 'name': 'Enumerable#max', 'type': 'instance method', 'path': 'language/enumerable/prototype/max' }, +'Ajax.PeriodicalUpdater': { 'name': 'Ajax.PeriodicalUpdater', 'type': 'class', 'path': 'ajax/ajax/periodicalupdater' }, +'Form.serializeElements': { 'name': 'Form.serializeElements', 'type': 'class method', 'path': 'dom/form/serializeelements' }, +'Hash#set': { 'name': 'Hash#set', 'type': 'instance method', 'path': 'language/hash/prototype/set' }, +'Date#toJSON': { 'name': 'Date#toJSON', 'type': 'instance method', 'path': 'language/date/prototype/tojson' }, +'Form.Element#clear': { 'name': 'Form.Element#clear', 'type': 'instance method', 'path': 'dom/form/element/prototype/clear' }, +'Element.Offset#relativeTo': { 'name': 'Element.Offset#relativeTo', 'type': 'instance method', 'path': 'dom/element/offset/prototype/relativeto' }, +'Array#without': { 'name': 'Array#without', 'type': 'instance method', 'path': 'language/array/prototype/without' }, +'Form.Observer': { 'name': 'Form.Observer', 'type': 'class', 'path': 'dom/form/observer' }, +'Hash': { 'name': 'Hash', 'type': 'class', 'path': 'language/hash' }, +'new Form.Element.Observer': { 'name': 'new Form.Element.Observer', 'type': 'constructor', 'path': 'dom/form/element/observer/new' }, +'Element#toggleClassName': { 'name': 'Element#toggleClassName', 'type': 'instance method', 'path': 'dom/element/prototype/toggleclassname' }, +'Selector.findElement': { 'name': 'Selector.findElement', 'type': 'class method', 'path': 'dom/selector/findelement' }, +'Array#reverse': { 'name': 'Array#reverse', 'type': 'instance method', 'path': 'language/array/prototype/reverse' }, +'new Hash': { 'name': 'new Hash', 'type': 'constructor', 'path': 'language/hash/new' }, +'Enumerable#eachSlice': { 'name': 'Enumerable#eachSlice', 'type': 'instance method', 'path': 'language/enumerable/prototype/eachslice' }, +'Element.siblings': { 'name': 'Element.siblings', 'type': 'class method', 'path': 'dom/element/siblings' }, +'ObjectRange#include': { 'name': 'ObjectRange#include', 'type': 'instance method', 'path': 'language/objectrange/prototype/include' }, +'Number#toPaddedString': { 'name': 'Number#toPaddedString', 'type': 'instance method', 'path': 'language/number/prototype/topaddedstring' }, +'Hash#each': { 'name': 'Hash#each', 'type': 'instance method', 'path': 'language/hash/prototype/each' }, +'Form#getInputs': { 'name': 'Form#getInputs', 'type': 'instance method', 'path': 'dom/form/prototype/getinputs' }, +'Element.wrap': { 'name': 'Element.wrap', 'type': 'class method', 'path': 'dom/element/wrap' }, +'Form#disable': { 'name': 'Form#disable', 'type': 'instance method', 'path': 'dom/form/prototype/disable' }, +'Hash#values': { 'name': 'Hash#values', 'type': 'instance method', 'path': 'language/hash/prototype/values' }, +'Element#viewportOffset': { 'name': 'Element#viewportOffset', 'type': 'instance method', 'path': 'dom/element/prototype/viewportoffset' }, +'Element#ancestors': { 'name': 'Element#ancestors', 'type': 'instance method', 'path': 'dom/element/prototype/ancestors' }, +'ObjectRange#start': { 'name': 'ObjectRange#start', 'type': 'instance property', 'path': 'language/objectrange/prototype/start' }, +'Element.immediateDescendants': { 'name': 'Element.immediateDescendants', 'type': 'class method', 'path': 'dom/element/immediatedescendants' }, +'Form.Element#disable': { 'name': 'Form.Element#disable', 'type': 'instance method', 'path': 'dom/form/element/prototype/disable' }, +'Hash#toObject': { 'name': 'Hash#toObject', 'type': 'instance method', 'path': 'language/hash/prototype/toobject' }, +'Event.stop': { 'name': 'Event.stop', 'type': 'class method', 'path': 'dom/event/stop' }, +'Ajax.Request#getHeader': { 'name': 'Ajax.Request#getHeader', 'type': 'instance method', 'path': 'ajax/ajax/request/prototype/getheader' }, +'Element#scrollTo': { 'name': 'Element#scrollTo', 'type': 'instance method', 'path': 'dom/element/prototype/scrollto' }, +'Form': { 'name': 'Form', 'type': 'namespace', 'path': 'dom/form' }, +'String#isJSON': { 'name': 'String#isJSON', 'type': 'instance method', 'path': 'language/string/prototype/isjson' }, +'Element#childElements': { 'name': 'Element#childElements', 'type': 'instance method', 'path': 'dom/element/prototype/childelements' }, +'Element#getStorage': { 'name': 'Element#getStorage', 'type': 'instance method', 'path': 'dom/element/prototype/getstorage' }, +'Element.Offset#toString': { 'name': 'Element.Offset#toString', 'type': 'instance method', 'path': 'dom/element/offset/prototype/tostring' }, +'Event#extend': { 'name': 'Event#extend', 'type': 'instance method', 'path': 'dom/event/prototype/extend' }, +'Event.element': { 'name': 'Event.element', 'type': 'class method', 'path': 'dom/event/element' }, +'new Abstract.TimedObserver': { 'name': 'new Abstract.TimedObserver', 'type': 'constructor', 'path': 'dom/abstract/timedobserver/new' }, +'Object.isUndefined': { 'name': 'Object.isUndefined', 'type': 'class method', 'path': 'language/object/isundefined' }, +'Function#argumentNames': { 'name': 'Function#argumentNames', 'type': 'instance method', 'path': 'language/function/prototype/argumentnames' }, +'Ajax.Response#transport': { 'name': 'Ajax.Response#transport', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/transport' }, +'Prototype.Selector.find': { 'name': 'Prototype.Selector.find', 'type': 'class method', 'path': 'language/prototype/selector/find' }, +'Ajax.activeRequestCount': { 'name': 'Ajax.activeRequestCount', 'type': 'class property', 'path': 'ajax/ajax/activerequestcount' }, +'Ajax.Response#getResponseHeader': { 'name': 'Ajax.Response#getResponseHeader', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getresponseheader' }, +'String#toArray': { 'name': 'String#toArray', 'type': 'instance method', 'path': 'language/string/prototype/toarray' }, +'document.observe': { 'name': 'document.observe', 'type': 'class method', 'path': 'dom/document/observe' }, +'Enumerable#each': { 'name': 'Enumerable#each', 'type': 'instance method', 'path': 'language/enumerable/prototype/each' }, +'Object.keys': { 'name': 'Object.keys', 'type': 'class method', 'path': 'language/object/keys' }, +'Prototype.BrowserFeatures': { 'name': 'Prototype.BrowserFeatures', 'type': 'namespace', 'path': 'language/prototype/browserfeatures' }, +'Element#readAttribute': { 'name': 'Element#readAttribute', 'type': 'instance method', 'path': 'dom/element/prototype/readattribute' }, +'Element.retrieve': { 'name': 'Element.retrieve', 'type': 'class method', 'path': 'dom/element/retrieve' }, +'Class#addMethods': { 'name': 'Class#addMethods', 'type': 'instance method', 'path': 'language/class/prototype/addmethods' }, +'Ajax.Response#getAllHeaders': { 'name': 'Ajax.Response#getAllHeaders', 'type': 'instance method', 'path': 'ajax/ajax/response/prototype/getallheaders' }, +'Enumerable#inGroupsOf': { 'name': 'Enumerable#inGroupsOf', 'type': 'instance method', 'path': 'language/enumerable/prototype/ingroupsof' }, +'Event#isRightClick': { 'name': 'Event#isRightClick', 'type': 'instance method', 'path': 'dom/event/prototype/isrightclick' }, +'Array#lastIndexOf': { 'name': 'Array#lastIndexOf', 'type': 'instance method', 'path': 'language/array/prototype/lastindexof' }, +'Function#methodize': { 'name': 'Function#methodize', 'type': 'instance method', 'path': 'language/function/prototype/methodize' }, +'$$': { 'name': '$$', 'type': 'utility', 'path': 'dom/dollardollar' }, +'Element.Offset#inspect': { 'name': 'Element.Offset#inspect', 'type': 'instance method', 'path': 'dom/element/offset/prototype/inspect' }, +'Element#absolutize': { 'name': 'Element#absolutize', 'type': 'instance method', 'path': 'dom/element/prototype/absolutize' }, +'Object.isFunction': { 'name': 'Object.isFunction', 'type': 'class method', 'path': 'language/object/isfunction' }, +'Element.undoClipping': { 'name': 'Element.undoClipping', 'type': 'class method', 'path': 'dom/element/undoclipping' }, +'Element.childElements': { 'name': 'Element.childElements', 'type': 'class method', 'path': 'dom/element/childelements' }, +'Form.Element.select': { 'name': 'Form.Element.select', 'type': 'class method', 'path': 'dom/form/element/select' }, +'Ajax': { 'name': 'Ajax', 'type': 'namespace', 'path': 'ajax/ajax' }, +'Element#undoClipping': { 'name': 'Element#undoClipping', 'type': 'instance method', 'path': 'dom/element/prototype/undoclipping' }, +'Element#match': { 'name': 'Element#match', 'type': 'instance method', 'path': 'dom/element/prototype/match' }, +'Form.Element.enable': { 'name': 'Form.Element.enable', 'type': 'class method', 'path': 'dom/form/element/enable' }, +'Enumerable#min': { 'name': 'Enumerable#min', 'type': 'instance method', 'path': 'language/enumerable/prototype/min' }, +'String#stripTags': { 'name': 'String#stripTags', 'type': 'instance method', 'path': 'language/string/prototype/striptags' }, +'Number#times': { 'name': 'Number#times', 'type': 'instance method', 'path': 'language/number/prototype/times' }, +'Date#toISOString': { 'name': 'Date#toISOString', 'type': 'instance method', 'path': 'language/date/prototype/toisostring' }, +'Element.on': { 'name': 'Element.on', 'type': 'class method', 'path': 'dom/element/on' }, +'Element.scrollTo': { 'name': 'Element.scrollTo', 'type': 'class method', 'path': 'dom/element/scrollto' }, +'Event.isLeftClick': { 'name': 'Event.isLeftClick', 'type': 'class method', 'path': 'dom/event/isleftclick' }, +'Element#identify': { 'name': 'Element#identify', 'type': 'instance method', 'path': 'dom/element/prototype/identify' }, +'document.viewport': { 'name': 'document.viewport', 'type': 'namespace', 'path': 'dom/document/viewport' }, +'Array#toArray': { 'name': 'Array#toArray', 'type': 'instance method', 'path': 'language/array/prototype/toarray' }, +'Element#clonePosition': { 'name': 'Element#clonePosition', 'type': 'instance method', 'path': 'dom/element/prototype/cloneposition' }, +'Object.isArray': { 'name': 'Object.isArray', 'type': 'class method', 'path': 'language/object/isarray' }, +'Selector.matchElements': { 'name': 'Selector.matchElements', 'type': 'class method', 'path': 'dom/selector/matchelements' }, +'Object.inspect': { 'name': 'Object.inspect', 'type': 'class method', 'path': 'language/object/inspect' }, +'String#inspect': { 'name': 'String#inspect', 'type': 'instance method', 'path': 'language/string/prototype/inspect' }, +'Array#size': { 'name': 'Array#size', 'type': 'instance method', 'path': 'language/array/prototype/size' }, +'Ajax.Response#responseText': { 'name': 'Ajax.Response#responseText', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsetext' }, +'Element#getStyle': { 'name': 'Element#getStyle', 'type': 'instance method', 'path': 'dom/element/prototype/getstyle' }, +'String#parseQuery': { 'name': 'String#parseQuery', 'type': 'instance method', 'path': 'language/string/prototype/parsequery' }, +'Ajax.Response#responseJSON': { 'name': 'Ajax.Response#responseJSON', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/responsejson' }, +'Element#insert': { 'name': 'Element#insert', 'type': 'instance method', 'path': 'dom/element/prototype/insert' }, +'new Ajax.Updater': { 'name': 'new Ajax.Updater', 'type': 'constructor', 'path': 'ajax/ajax/updater/new' }, +'Selector#match': { 'name': 'Selector#match', 'type': 'instance method', 'path': 'dom/selector/prototype/match' }, +'Ajax.Response#readyState': { 'name': 'Ajax.Response#readyState', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/readystate' }, +'Enumerable#filter': { 'name': 'Enumerable#filter', 'type': 'instance method', 'path': 'language/enumerable/prototype/filter' }, +'Form.focusFirstElement': { 'name': 'Form.focusFirstElement', 'type': 'class method', 'path': 'dom/form/focusfirstelement' }, +'Ajax.Response#headerJSON': { 'name': 'Ajax.Response#headerJSON', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/headerjson' }, +'Form#enable': { 'name': 'Form#enable', 'type': 'instance method', 'path': 'dom/form/prototype/enable' }, +'Form.Element#activate': { 'name': 'Form.Element#activate', 'type': 'instance method', 'path': 'dom/form/element/prototype/activate' }, +'Prototype.BrowserFeatures.ElementExtensions': { 'name': 'Prototype.BrowserFeatures.ElementExtensions', 'type': 'class property', 'path': 'language/prototype/browserfeatures/elementextensions' }, +'Event#pointerX': { 'name': 'Event#pointerX', 'type': 'instance method', 'path': 'dom/event/prototype/pointerx' }, +'Object.extend': { 'name': 'Object.extend', 'type': 'class method', 'path': 'language/object/extend' }, +'DOM section': { 'name': 'DOM section', 'type': 'section', 'path': 'dom' }, +'document.viewport.getWidth': { 'name': 'document.viewport.getWidth', 'type': 'class method', 'path': 'dom/document/viewport/getwidth' }, +'Element.getOffsetParent': { 'name': 'Element.getOffsetParent', 'type': 'class method', 'path': 'dom/element/getoffsetparent' }, +'Object.toJSON': { 'name': 'Object.toJSON', 'type': 'class method', 'path': 'language/object/tojson' }, +'PeriodicalExecuter#stop': { 'name': 'PeriodicalExecuter#stop', 'type': 'instance method', 'path': 'language/periodicalexecuter/prototype/stop' }, +'Function#bindAsEventListener': { 'name': 'Function#bindAsEventListener', 'type': 'instance method', 'path': 'language/function/prototype/bindaseventlistener' }, +'Event#pointerY': { 'name': 'Event#pointerY', 'type': 'instance method', 'path': 'dom/event/prototype/pointery' }, +'Ajax.Response': { 'name': 'Ajax.Response', 'type': 'class', 'path': 'ajax/ajax/response' }, +'Hash#toJSON': { 'name': 'Hash#toJSON', 'type': 'instance method', 'path': 'language/hash/prototype/tojson' }, +'Hash#keys': { 'name': 'Hash#keys', 'type': 'instance method', 'path': 'language/hash/prototype/keys' }, +'Element#store': { 'name': 'Element#store', 'type': 'instance method', 'path': 'dom/element/prototype/store' }, +'Element.replace': { 'name': 'Element.replace', 'type': 'class method', 'path': 'dom/element/replace' }, +'Element.descendants': { 'name': 'Element.descendants', 'type': 'class method', 'path': 'dom/element/descendants' }, +'Prototype.emptyFunction': { 'name': 'Prototype.emptyFunction', 'type': 'class method', 'path': 'language/prototype/emptyfunction' }, +'Enumerable#reject': { 'name': 'Enumerable#reject', 'type': 'instance method', 'path': 'language/enumerable/prototype/reject' }, +'Enumerable#some': { 'name': 'Enumerable#some', 'type': 'instance method', 'path': 'language/enumerable/prototype/some' }, +'Enumerable#partition': { 'name': 'Enumerable#partition', 'type': 'instance method', 'path': 'language/enumerable/prototype/partition' }, +'Hash#update': { 'name': 'Hash#update', 'type': 'instance method', 'path': 'language/hash/prototype/update' }, +'Form#focusFirstElement': { 'name': 'Form#focusFirstElement', 'type': 'instance method', 'path': 'dom/form/prototype/focusfirstelement' }, +'Element#previousSiblings': { 'name': 'Element#previousSiblings', 'type': 'instance method', 'path': 'dom/element/prototype/previoussiblings' }, +'Element.clonePosition': { 'name': 'Element.clonePosition', 'type': 'class method', 'path': 'dom/element/cloneposition' }, +'Ajax.Response#status': { 'name': 'Ajax.Response#status', 'type': 'instance property', 'path': 'ajax/ajax/response/prototype/status' }, +'Element#nextSiblings': { 'name': 'Element#nextSiblings', 'type': 'instance method', 'path': 'dom/element/prototype/nextsiblings' }, +'Element.getLayout': { 'name': 'Element.getLayout', 'type': 'class method', 'path': 'dom/element/getlayout' }, +'Number#succ': { 'name': 'Number#succ', 'type': 'instance method', 'path': 'language/number/prototype/succ' }, +'Element#measure': { 'name': 'Element#measure', 'type': 'instance method', 'path': 'dom/element/prototype/measure' }, +'Element#update': { 'name': 'Element#update', 'type': 'instance method', 'path': 'dom/element/prototype/update' }, +'Element#stopObserving': { 'name': 'Element#stopObserving', 'type': 'instance method', 'path': 'dom/element/prototype/stopobserving' }, +'Element.identify': { 'name': 'Element.identify', 'type': 'class method', 'path': 'dom/element/identify' }, +'Element.hasAttribute': { 'name': 'Element.hasAttribute', 'type': 'class method', 'path': 'dom/element/hasattribute' }, +'document.viewport.getHeight': { 'name': 'document.viewport.getHeight', 'type': 'class method', 'path': 'dom/document/viewport/getheight' }, +'Try.these': { 'name': 'Try.these', 'type': 'class method', 'path': 'language/try/these' }, +'Element#adjacent': { 'name': 'Element#adjacent', 'type': 'instance method', 'path': 'dom/element/prototype/adjacent' }, +'Enumerable#size': { 'name': 'Enumerable#size', 'type': 'instance method', 'path': 'language/enumerable/prototype/size' }, +'new Ajax.Request': { 'name': 'new Ajax.Request', 'type': 'constructor', 'path': 'ajax/ajax/request/new' }, +'Element#hasAttribute': { 'name': 'Element#hasAttribute', 'type': 'instance method', 'path': 'dom/element/prototype/hasattribute' }, +'Function#wrap': { 'name': 'Function#wrap', 'type': 'instance method', 'path': 'language/function/prototype/wrap' }, +'document.loaded': { 'name': 'document.loaded', 'type': 'class property', 'path': 'dom/document/loaded' }, +'Element#classNames': { 'name': 'Element#classNames', 'type': 'instance method', 'path': 'dom/element/prototype/classnames' }, +'Element#empty': { 'name': 'Element#empty', 'type': 'instance method', 'path': 'dom/element/prototype/empty' }, +'Function#defer': { 'name': 'Function#defer', 'type': 'instance method', 'path': 'language/function/prototype/defer' }, +'Array#intersect': { 'name': 'Array#intersect', 'type': 'instance method', 'path': 'language/array/prototype/intersect' }, +'Element.previousSiblings': { 'name': 'Element.previousSiblings', 'type': 'class method', 'path': 'dom/element/previoussiblings' }, +'Form.Element.activate': { 'name': 'Form.Element.activate', 'type': 'class method', 'path': 'dom/form/element/activate' }, +'new Template': { 'name': 'new Template', 'type': 'constructor', 'path': 'language/template/new' }, +'Enumerable#findAll': { 'name': 'Enumerable#findAll', 'type': 'instance method', 'path': 'language/enumerable/prototype/findall' }, +'Form.reset': { 'name': 'Form.reset', 'type': 'class method', 'path': 'dom/form/reset' }, +'Function#curry': { 'name': 'Function#curry', 'type': 'instance method', 'path': 'language/function/prototype/curry' } +}; \ No newline at end of file diff --git a/doc/javascripts/prototype.js b/doc/javascripts/prototype.js new file mode 100644 index 000000000..9fe6e1243 --- /dev/null +++ b/doc/javascripts/prototype.js @@ -0,0 +1,4874 @@ +/* Prototype JavaScript framework, version 1.6.1 + * (c) 2005-2009 Sam Stephenson + * + * Prototype is freely distributable under the terms of an MIT-style license. + * For details, see the Prototype web site: http://www.prototypejs.org/ + * + *--------------------------------------------------------------------------*/ + +var Prototype = { + Version: '1.6.1', + + Browser: (function(){ + var ua = navigator.userAgent; + var isOpera = Object.prototype.toString.call(window.opera) == '[object Opera]'; + return { + IE: !!window.attachEvent && !isOpera, + Opera: isOpera, + WebKit: ua.indexOf('AppleWebKit/') > -1, + Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1, + MobileSafari: /Apple.*Mobile.*Safari/.test(ua) + } + })(), + + BrowserFeatures: { + XPath: !!document.evaluate, + SelectorsAPI: !!document.querySelector, + ElementExtensions: (function() { + var constructor = window.Element || window.HTMLElement; + return !!(constructor && constructor.prototype); + })(), + SpecificElementExtensions: (function() { + if (typeof window.HTMLDivElement !== 'undefined') + return true; + + var div = document.createElement('div'); + var form = document.createElement('form'); + var isSupported = false; + + if (div['__proto__'] && (div['__proto__'] !== form['__proto__'])) { + isSupported = true; + } + + div = form = null; + + return isSupported; + })() + }, + + ScriptFragment: ']*>([\\S\\s]*?)<\/script>', + JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/, + + emptyFunction: function() { }, + K: function(x) { return x } +}; + +if (Prototype.Browser.MobileSafari) + Prototype.BrowserFeatures.SpecificElementExtensions = false; + + +var Abstract = { }; + + +var Try = { + these: function() { + var returnValue; + + for (var i = 0, length = arguments.length; i < length; i++) { + var lambda = arguments[i]; + try { + returnValue = lambda(); + break; + } catch (e) { } + } + + return returnValue; + } +}; + +/* Based on Alex Arnell's inheritance implementation. */ + +var Class = (function() { + function subclass() {}; + function create() { + var parent = null, properties = $A(arguments); + if (Object.isFunction(properties[0])) + parent = properties.shift(); + + function klass() { + this.initialize.apply(this, arguments); + } + + Object.extend(klass, Class.Methods); + klass.superclass = parent; + klass.subclasses = []; + + if (parent) { + subclass.prototype = parent.prototype; + klass.prototype = new subclass; + parent.subclasses.push(klass); + } + + for (var i = 0; i < properties.length; i++) + klass.addMethods(properties[i]); + + if (!klass.prototype.initialize) + klass.prototype.initialize = Prototype.emptyFunction; + + klass.prototype.constructor = klass; + return klass; + } + + function addMethods(source) { + var ancestor = this.superclass && this.superclass.prototype; + var properties = Object.keys(source); + + if (!Object.keys({ toString: true }).length) { + if (source.toString != Object.prototype.toString) + properties.push("toString"); + if (source.valueOf != Object.prototype.valueOf) + properties.push("valueOf"); + } + + for (var i = 0, length = properties.length; i < length; i++) { + var property = properties[i], value = source[property]; + if (ancestor && Object.isFunction(value) && + value.argumentNames().first() == "$super") { + var method = value; + value = (function(m) { + return function() { return ancestor[m].apply(this, arguments); }; + })(property).wrap(method); + + value.valueOf = method.valueOf.bind(method); + value.toString = method.toString.bind(method); + } + this.prototype[property] = value; + } + + return this; + } + + return { + create: create, + Methods: { + addMethods: addMethods + } + }; +})(); +(function() { + + var _toString = Object.prototype.toString; + + function extend(destination, source) { + for (var property in source) + destination[property] = source[property]; + return destination; + } + + function inspect(object) { + try { + if (isUndefined(object)) return 'undefined'; + if (object === null) return 'null'; + return object.inspect ? object.inspect() : String(object); + } catch (e) { + if (e instanceof RangeError) return '...'; + throw e; + } + } + + function toJSON(object) { + var type = typeof object; + switch (type) { + case 'undefined': + case 'function': + case 'unknown': return; + case 'boolean': return object.toString(); + } + + if (object === null) return 'null'; + if (object.toJSON) return object.toJSON(); + if (isElement(object)) return; + + var results = []; + for (var property in object) { + var value = toJSON(object[property]); + if (!isUndefined(value)) + results.push(property.toJSON() + ': ' + value); + } + + return '{' + results.join(', ') + '}'; + } + + function toQueryString(object) { + return $H(object).toQueryString(); + } + + function toHTML(object) { + return object && object.toHTML ? object.toHTML() : String.interpret(object); + } + + function keys(object) { + var results = []; + for (var property in object) + results.push(property); + return results; + } + + function values(object) { + var results = []; + for (var property in object) + results.push(object[property]); + return results; + } + + function clone(object) { + return extend({ }, object); + } + + function isElement(object) { + return !!(object && object.nodeType == 1); + } + + function isArray(object) { + return _toString.call(object) == "[object Array]"; + } + + + function isHash(object) { + return object instanceof Hash; + } + + function isFunction(object) { + return typeof object === "function"; + } + + function isString(object) { + return _toString.call(object) == "[object String]"; + } + + function isNumber(object) { + return _toString.call(object) == "[object Number]"; + } + + function isUndefined(object) { + return typeof object === "undefined"; + } + + extend(Object, { + extend: extend, + inspect: inspect, + toJSON: toJSON, + toQueryString: toQueryString, + toHTML: toHTML, + keys: keys, + values: values, + clone: clone, + isElement: isElement, + isArray: isArray, + isHash: isHash, + isFunction: isFunction, + isString: isString, + isNumber: isNumber, + isUndefined: isUndefined + }); +})(); +Object.extend(Function.prototype, (function() { + var slice = Array.prototype.slice; + + function update(array, args) { + var arrayLength = array.length, length = args.length; + while (length--) array[arrayLength + length] = args[length]; + return array; + } + + function merge(array, args) { + array = slice.call(array, 0); + return update(array, args); + } + + function argumentNames() { + var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] + .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') + .replace(/\s+/g, '').split(','); + return names.length == 1 && !names[0] ? [] : names; + } + + function bind(context) { + if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this; + var __method = this, args = slice.call(arguments, 1); + return function() { + var a = merge(args, arguments); + return __method.apply(context, a); + } + } + + function bindAsEventListener(context) { + var __method = this, args = slice.call(arguments, 1); + return function(event) { + var a = update([event || window.event], args); + return __method.apply(context, a); + } + } + + function curry() { + if (!arguments.length) return this; + var __method = this, args = slice.call(arguments, 0); + return function() { + var a = merge(args, arguments); + return __method.apply(this, a); + } + } + + function delay(timeout) { + var __method = this, args = slice.call(arguments, 1); + timeout = timeout * 1000 + return window.setTimeout(function() { + return __method.apply(__method, args); + }, timeout); + } + + function defer() { + var args = update([0.01], arguments); + return this.delay.apply(this, args); + } + + function wrap(wrapper) { + var __method = this; + return function() { + var a = update([__method.bind(this)], arguments); + return wrapper.apply(this, a); + } + } + + function methodize() { + if (this._methodized) return this._methodized; + var __method = this; + return this._methodized = function() { + var a = update([this], arguments); + return __method.apply(null, a); + }; + } + + return { + argumentNames: argumentNames, + bind: bind, + bindAsEventListener: bindAsEventListener, + curry: curry, + delay: delay, + defer: defer, + wrap: wrap, + methodize: methodize + } +})()); + + +Date.prototype.toJSON = function() { + return '"' + this.getUTCFullYear() + '-' + + (this.getUTCMonth() + 1).toPaddedString(2) + '-' + + this.getUTCDate().toPaddedString(2) + 'T' + + this.getUTCHours().toPaddedString(2) + ':' + + this.getUTCMinutes().toPaddedString(2) + ':' + + this.getUTCSeconds().toPaddedString(2) + 'Z"'; +}; + + +RegExp.prototype.match = RegExp.prototype.test; + +RegExp.escape = function(str) { + return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); +}; +var PeriodicalExecuter = Class.create({ + initialize: function(callback, frequency) { + this.callback = callback; + this.frequency = frequency; + this.currentlyExecuting = false; + + this.registerCallback(); + }, + + registerCallback: function() { + this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); + }, + + execute: function() { + this.callback(this); + }, + + stop: function() { + if (!this.timer) return; + clearInterval(this.timer); + this.timer = null; + }, + + onTimerEvent: function() { + if (!this.currentlyExecuting) { + try { + this.currentlyExecuting = true; + this.execute(); + this.currentlyExecuting = false; + } catch(e) { + this.currentlyExecuting = false; + throw e; + } + } + } +}); +Object.extend(String, { + interpret: function(value) { + return value == null ? '' : String(value); + }, + specialChar: { + '\b': '\\b', + '\t': '\\t', + '\n': '\\n', + '\f': '\\f', + '\r': '\\r', + '\\': '\\\\' + } +}); + +Object.extend(String.prototype, (function() { + + function prepareReplacement(replacement) { + if (Object.isFunction(replacement)) return replacement; + var template = new Template(replacement); + return function(match) { return template.evaluate(match) }; + } + + function gsub(pattern, replacement) { + var result = '', source = this, match; + replacement = prepareReplacement(replacement); + + if (Object.isString(pattern)) + pattern = RegExp.escape(pattern); + + if (!(pattern.length || pattern.source)) { + replacement = replacement(''); + return replacement + source.split('').join(replacement) + replacement; + } + + while (source.length > 0) { + if (match = source.match(pattern)) { + result += source.slice(0, match.index); + result += String.interpret(replacement(match)); + source = source.slice(match.index + match[0].length); + } else { + result += source, source = ''; + } + } + return result; + } + + function sub(pattern, replacement, count) { + replacement = prepareReplacement(replacement); + count = Object.isUndefined(count) ? 1 : count; + + return this.gsub(pattern, function(match) { + if (--count < 0) return match[0]; + return replacement(match); + }); + } + + function scan(pattern, iterator) { + this.gsub(pattern, iterator); + return String(this); + } + + function truncate(length, truncation) { + length = length || 30; + truncation = Object.isUndefined(truncation) ? '...' : truncation; + return this.length > length ? + this.slice(0, length - truncation.length) + truncation : String(this); + } + + function strip() { + return this.replace(/^\s+/, '').replace(/\s+$/, ''); + } + + function stripTags() { + return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?>|<\/\w+>/gi, ''); + } + + function stripScripts() { + return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); + } + + function extractScripts() { + var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); + var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); + return (this.match(matchAll) || []).map(function(scriptTag) { + return (scriptTag.match(matchOne) || ['', ''])[1]; + }); + } + + function evalScripts() { + return this.extractScripts().map(function(script) { return eval(script) }); + } + + function escapeHTML() { + return this.replace(/&/g,'&').replace(//g,'>'); + } + + function unescapeHTML() { + return this.stripTags().replace(/</g,'<').replace(/>/g,'>').replace(/&/g,'&'); + } + + + function toQueryParams(separator) { + var match = this.strip().match(/([^?#]*)(#.*)?$/); + if (!match) return { }; + + return match[1].split(separator || '&').inject({ }, function(hash, pair) { + if ((pair = pair.split('='))[0]) { + var key = decodeURIComponent(pair.shift()); + var value = pair.length > 1 ? pair.join('=') : pair[0]; + if (value != undefined) value = decodeURIComponent(value); + + if (key in hash) { + if (!Object.isArray(hash[key])) hash[key] = [hash[key]]; + hash[key].push(value); + } + else hash[key] = value; + } + return hash; + }); + } + + function toArray() { + return this.split(''); + } + + function succ() { + return this.slice(0, this.length - 1) + + String.fromCharCode(this.charCodeAt(this.length - 1) + 1); + } + + function times(count) { + return count < 1 ? '' : new Array(count + 1).join(this); + } + + function camelize() { + var parts = this.split('-'), len = parts.length; + if (len == 1) return parts[0]; + + var camelized = this.charAt(0) == '-' + ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) + : parts[0]; + + for (var i = 1; i < len; i++) + camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1); + + return camelized; + } + + function capitalize() { + return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase(); + } + + function underscore() { + return this.replace(/::/g, '/') + .replace(/([A-Z]+)([A-Z][a-z])/g, '$1_$2') + .replace(/([a-z\d])([A-Z])/g, '$1_$2') + .replace(/-/g, '_') + .toLowerCase(); + } + + function dasherize() { + return this.replace(/_/g, '-'); + } + + function inspect(useDoubleQuotes) { + var escapedString = this.replace(/[\x00-\x1f\\]/g, function(character) { + if (character in String.specialChar) { + return String.specialChar[character]; + } + return '\\u00' + character.charCodeAt().toPaddedString(2, 16); + }); + if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"'; + return "'" + escapedString.replace(/'/g, '\\\'') + "'"; + } + + function toJSON() { + return this.inspect(true); + } + + function unfilterJSON(filter) { + return this.replace(filter || Prototype.JSONFilter, '$1'); + } + + function isJSON() { + var str = this; + if (str.blank()) return false; + str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, ''); + return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str); + } + + function evalJSON(sanitize) { + var json = this.unfilterJSON(); + try { + if (!sanitize || json.isJSON()) return eval('(' + json + ')'); + } catch (e) { } + throw new SyntaxError('Badly formed JSON string: ' + this.inspect()); + } + + function include(pattern) { + return this.indexOf(pattern) > -1; + } + + function startsWith(pattern) { + return this.indexOf(pattern) === 0; + } + + function endsWith(pattern) { + var d = this.length - pattern.length; + return d >= 0 && this.lastIndexOf(pattern) === d; + } + + function empty() { + return this == ''; + } + + function blank() { + return /^\s*$/.test(this); + } + + function interpolate(object, pattern) { + return new Template(this, pattern).evaluate(object); + } + + return { + gsub: gsub, + sub: sub, + scan: scan, + truncate: truncate, + strip: String.prototype.trim ? String.prototype.trim : strip, + stripTags: stripTags, + stripScripts: stripScripts, + extractScripts: extractScripts, + evalScripts: evalScripts, + escapeHTML: escapeHTML, + unescapeHTML: unescapeHTML, + toQueryParams: toQueryParams, + parseQuery: toQueryParams, + toArray: toArray, + succ: succ, + times: times, + camelize: camelize, + capitalize: capitalize, + underscore: underscore, + dasherize: dasherize, + inspect: inspect, + toJSON: toJSON, + unfilterJSON: unfilterJSON, + isJSON: isJSON, + evalJSON: evalJSON, + include: include, + startsWith: startsWith, + endsWith: endsWith, + empty: empty, + blank: blank, + interpolate: interpolate + }; +})()); + +var Template = Class.create({ + initialize: function(template, pattern) { + this.template = template.toString(); + this.pattern = pattern || Template.Pattern; + }, + + evaluate: function(object) { + if (object && Object.isFunction(object.toTemplateReplacements)) + object = object.toTemplateReplacements(); + + return this.template.gsub(this.pattern, function(match) { + if (object == null) return (match[1] + ''); + + var before = match[1] || ''; + if (before == '\\') return match[2]; + + var ctx = object, expr = match[3]; + var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/; + match = pattern.exec(expr); + if (match == null) return before; + + while (match != null) { + var comp = match[1].startsWith('[') ? match[2].replace(/\\\\]/g, ']') : match[1]; + ctx = ctx[comp]; + if (null == ctx || '' == match[3]) break; + expr = expr.substring('[' == match[3] ? match[1].length : match[0].length); + match = pattern.exec(expr); + } + + return before + String.interpret(ctx); + }); + } +}); +Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/; + +var $break = { }; + +var Enumerable = (function() { + function each(iterator, context) { + var index = 0; + try { + this._each(function(value) { + iterator.call(context, value, index++); + }); + } catch (e) { + if (e != $break) throw e; + } + return this; + } + + function eachSlice(number, iterator, context) { + var index = -number, slices = [], array = this.toArray(); + if (number < 1) return array; + while ((index += number) < array.length) + slices.push(array.slice(index, index+number)); + return slices.collect(iterator, context); + } + + function all(iterator, context) { + iterator = iterator || Prototype.K; + var result = true; + this.each(function(value, index) { + result = result && !!iterator.call(context, value, index); + if (!result) throw $break; + }); + return result; + } + + function any(iterator, context) { + iterator = iterator || Prototype.K; + var result = false; + this.each(function(value, index) { + if (result = !!iterator.call(context, value, index)) + throw $break; + }); + return result; + } + + function collect(iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + this.each(function(value, index) { + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function detect(iterator, context) { + var result; + this.each(function(value, index) { + if (iterator.call(context, value, index)) { + result = value; + throw $break; + } + }); + return result; + } + + function findAll(iterator, context) { + var results = []; + this.each(function(value, index) { + if (iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function grep(filter, iterator, context) { + iterator = iterator || Prototype.K; + var results = []; + + if (Object.isString(filter)) + filter = new RegExp(RegExp.escape(filter)); + + this.each(function(value, index) { + if (filter.match(value)) + results.push(iterator.call(context, value, index)); + }); + return results; + } + + function include(object) { + if (Object.isFunction(this.indexOf)) + if (this.indexOf(object) != -1) return true; + + var found = false; + this.each(function(value) { + if (value == object) { + found = true; + throw $break; + } + }); + return found; + } + + function inGroupsOf(number, fillWith) { + fillWith = Object.isUndefined(fillWith) ? null : fillWith; + return this.eachSlice(number, function(slice) { + while(slice.length < number) slice.push(fillWith); + return slice; + }); + } + + function inject(memo, iterator, context) { + this.each(function(value, index) { + memo = iterator.call(context, memo, value, index); + }); + return memo; + } + + function invoke(method) { + var args = $A(arguments).slice(1); + return this.map(function(value) { + return value[method].apply(value, args); + }); + } + + function max(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value >= result) + result = value; + }); + return result; + } + + function min(iterator, context) { + iterator = iterator || Prototype.K; + var result; + this.each(function(value, index) { + value = iterator.call(context, value, index); + if (result == null || value < result) + result = value; + }); + return result; + } + + function partition(iterator, context) { + iterator = iterator || Prototype.K; + var trues = [], falses = []; + this.each(function(value, index) { + (iterator.call(context, value, index) ? + trues : falses).push(value); + }); + return [trues, falses]; + } + + function pluck(property) { + var results = []; + this.each(function(value) { + results.push(value[property]); + }); + return results; + } + + function reject(iterator, context) { + var results = []; + this.each(function(value, index) { + if (!iterator.call(context, value, index)) + results.push(value); + }); + return results; + } + + function sortBy(iterator, context) { + return this.map(function(value, index) { + return { + value: value, + criteria: iterator.call(context, value, index) + }; + }).sort(function(left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }).pluck('value'); + } + + function toArray() { + return this.map(); + } + + function zip() { + var iterator = Prototype.K, args = $A(arguments); + if (Object.isFunction(args.last())) + iterator = args.pop(); + + var collections = [this].concat(args).map($A); + return this.map(function(value, index) { + return iterator(collections.pluck(index)); + }); + } + + function size() { + return this.toArray().length; + } + + function inspect() { + return '#'; + } + + + + + + + + + + return { + each: each, + eachSlice: eachSlice, + all: all, + every: all, + any: any, + some: any, + collect: collect, + map: collect, + detect: detect, + findAll: findAll, + select: findAll, + filter: findAll, + grep: grep, + include: include, + member: include, + inGroupsOf: inGroupsOf, + inject: inject, + invoke: invoke, + max: max, + min: min, + partition: partition, + pluck: pluck, + reject: reject, + sortBy: sortBy, + toArray: toArray, + entries: toArray, + zip: zip, + size: size, + inspect: inspect, + find: detect + }; +})(); +function $A(iterable) { + if (!iterable) return []; + if ('toArray' in Object(iterable)) return iterable.toArray(); + var length = iterable.length || 0, results = new Array(length); + while (length--) results[length] = iterable[length]; + return results; +} + +function $w(string) { + if (!Object.isString(string)) return []; + string = string.strip(); + return string ? string.split(/\s+/) : []; +} + +Array.from = $A; + + +(function() { + var arrayProto = Array.prototype, + slice = arrayProto.slice, + _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available + + function each(iterator) { + for (var i = 0, length = this.length; i < length; i++) + iterator(this[i]); + } + if (!_each) _each = each; + + function clear() { + this.length = 0; + return this; + } + + function first() { + return this[0]; + } + + function last() { + return this[this.length - 1]; + } + + function compact() { + return this.select(function(value) { + return value != null; + }); + } + + function flatten() { + return this.inject([], function(array, value) { + if (Object.isArray(value)) + return array.concat(value.flatten()); + array.push(value); + return array; + }); + } + + function without() { + var values = slice.call(arguments, 0); + return this.select(function(value) { + return !values.include(value); + }); + } + + function reverse(inline) { + return (inline !== false ? this : this.toArray())._reverse(); + } + + function uniq(sorted) { + return this.inject([], function(array, value, index) { + if (0 == index || (sorted ? array.last() != value : !array.include(value))) + array.push(value); + return array; + }); + } + + function intersect(array) { + return this.uniq().findAll(function(item) { + return array.detect(function(value) { return item === value }); + }); + } + + + function clone() { + return slice.call(this, 0); + } + + function size() { + return this.length; + } + + function inspect() { + return '[' + this.map(Object.inspect).join(', ') + ']'; + } + + function toJSON() { + var results = []; + this.each(function(object) { + var value = Object.toJSON(object); + if (!Object.isUndefined(value)) results.push(value); + }); + return '[' + results.join(', ') + ']'; + } + + function indexOf(item, i) { + i || (i = 0); + var length = this.length; + if (i < 0) i = length + i; + for (; i < length; i++) + if (this[i] === item) return i; + return -1; + } + + function lastIndexOf(item, i) { + i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1; + var n = this.slice(0, i).reverse().indexOf(item); + return (n < 0) ? n : i - n - 1; + } + + function concat() { + var array = slice.call(this, 0), item; + for (var i = 0, length = arguments.length; i < length; i++) { + item = arguments[i]; + if (Object.isArray(item) && !('callee' in item)) { + for (var j = 0, arrayLength = item.length; j < arrayLength; j++) + array.push(item[j]); + } else { + array.push(item); + } + } + return array; + } + + Object.extend(arrayProto, Enumerable); + + if (!arrayProto._reverse) + arrayProto._reverse = arrayProto.reverse; + + Object.extend(arrayProto, { + _each: _each, + clear: clear, + first: first, + last: last, + compact: compact, + flatten: flatten, + without: without, + reverse: reverse, + uniq: uniq, + intersect: intersect, + clone: clone, + toArray: clone, + size: size, + inspect: inspect, + toJSON: toJSON + }); + + var CONCAT_ARGUMENTS_BUGGY = (function() { + return [].concat(arguments)[0][0] !== 1; + })(1,2) + + if (CONCAT_ARGUMENTS_BUGGY) arrayProto.concat = concat; + + if (!arrayProto.indexOf) arrayProto.indexOf = indexOf; + if (!arrayProto.lastIndexOf) arrayProto.lastIndexOf = lastIndexOf; +})(); +function $H(object) { + return new Hash(object); +}; + +var Hash = Class.create(Enumerable, (function() { + function initialize(object) { + this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); + } + + function _each(iterator) { + for (var key in this._object) { + var value = this._object[key], pair = [key, value]; + pair.key = key; + pair.value = value; + iterator(pair); + } + } + + function set(key, value) { + return this._object[key] = value; + } + + function get(key) { + if (this._object[key] !== Object.prototype[key]) + return this._object[key]; + } + + function unset(key) { + var value = this._object[key]; + delete this._object[key]; + return value; + } + + function toObject() { + return Object.clone(this._object); + } + + function keys() { + return this.pluck('key'); + } + + function values() { + return this.pluck('value'); + } + + function index(value) { + var match = this.detect(function(pair) { + return pair.value === value; + }); + return match && match.key; + } + + function merge(object) { + return this.clone().update(object); + } + + function update(object) { + return new Hash(object).inject(this, function(result, pair) { + result.set(pair.key, pair.value); + return result; + }); + } + + function toQueryPair(key, value) { + if (Object.isUndefined(value)) return key; + return key + '=' + encodeURIComponent(String.interpret(value)); + } + + function toQueryString() { + return this.inject([], function(results, pair) { + var key = encodeURIComponent(pair.key), values = pair.value; + + if (values && typeof values == 'object') { + if (Object.isArray(values)) + return results.concat(values.map(toQueryPair.curry(key))); + } else results.push(toQueryPair(key, values)); + return results; + }).join('&'); + } + + function inspect() { + return '#'; + } + + function toJSON() { + return Object.toJSON(this.toObject()); + } + + function clone() { + return new Hash(this); + } + + return { + initialize: initialize, + _each: _each, + set: set, + get: get, + unset: unset, + toObject: toObject, + toTemplateReplacements: toObject, + keys: keys, + values: values, + index: index, + merge: merge, + update: update, + toQueryString: toQueryString, + inspect: inspect, + toJSON: toJSON, + clone: clone + }; +})()); + +Hash.from = $H; +Object.extend(Number.prototype, (function() { + function toColorPart() { + return this.toPaddedString(2, 16); + } + + function succ() { + return this + 1; + } + + function times(iterator, context) { + $R(0, this, true).each(iterator, context); + return this; + } + + function toPaddedString(length, radix) { + var string = this.toString(radix || 10); + return '0'.times(length - string.length) + string; + } + + function toJSON() { + return isFinite(this) ? this.toString() : 'null'; + } + + function abs() { + return Math.abs(this); + } + + function round() { + return Math.round(this); + } + + function ceil() { + return Math.ceil(this); + } + + function floor() { + return Math.floor(this); + } + + return { + toColorPart: toColorPart, + succ: succ, + times: times, + toPaddedString: toPaddedString, + toJSON: toJSON, + abs: abs, + round: round, + ceil: ceil, + floor: floor + }; +})()); + +function $R(start, end, exclusive) { + return new ObjectRange(start, end, exclusive); +} + +var ObjectRange = Class.create(Enumerable, (function() { + function initialize(start, end, exclusive) { + this.start = start; + this.end = end; + this.exclusive = exclusive; + } + + function _each(iterator) { + var value = this.start; + while (this.include(value)) { + iterator(value); + value = value.succ(); + } + } + + function include(value) { + if (value < this.start) + return false; + if (this.exclusive) + return value < this.end; + return value <= this.end; + } + + return { + initialize: initialize, + _each: _each, + include: include + }; +})()); + + + +var Ajax = { + getTransport: function() { + return Try.these( + function() {return new XMLHttpRequest()}, + function() {return new ActiveXObject('Msxml2.XMLHTTP')}, + function() {return new ActiveXObject('Microsoft.XMLHTTP')} + ) || false; + }, + + activeRequestCount: 0 +}; + +Ajax.Responders = { + responders: [], + + _each: function(iterator) { + this.responders._each(iterator); + }, + + register: function(responder) { + if (!this.include(responder)) + this.responders.push(responder); + }, + + unregister: function(responder) { + this.responders = this.responders.without(responder); + }, + + dispatch: function(callback, request, transport, json) { + this.each(function(responder) { + if (Object.isFunction(responder[callback])) { + try { + responder[callback].apply(responder, [request, transport, json]); + } catch (e) { } + } + }); + } +}; + +Object.extend(Ajax.Responders, Enumerable); + +Ajax.Responders.register({ + onCreate: function() { Ajax.activeRequestCount++ }, + onComplete: function() { Ajax.activeRequestCount-- } +}); +Ajax.Base = Class.create({ + initialize: function(options) { + this.options = { + method: 'post', + asynchronous: true, + contentType: 'application/x-www-form-urlencoded', + encoding: 'UTF-8', + parameters: '', + evalJSON: true, + evalJS: true + }; + Object.extend(this.options, options || { }); + + this.options.method = this.options.method.toLowerCase(); + + if (Object.isString(this.options.parameters)) + this.options.parameters = this.options.parameters.toQueryParams(); + else if (Object.isHash(this.options.parameters)) + this.options.parameters = this.options.parameters.toObject(); + } +}); +Ajax.Request = Class.create(Ajax.Base, { + _complete: false, + + initialize: function($super, url, options) { + $super(options); + this.transport = Ajax.getTransport(); + this.request(url); + }, + + request: function(url) { + this.url = url; + this.method = this.options.method; + var params = Object.clone(this.options.parameters); + + if (!['get', 'post'].include(this.method)) { + params['_method'] = this.method; + this.method = 'post'; + } + + this.parameters = params; + + if (params = Object.toQueryString(params)) { + if (this.method == 'get') + this.url += (this.url.include('?') ? '&' : '?') + params; + else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) + params += '&_='; + } + + try { + var response = new Ajax.Response(this); + if (this.options.onCreate) this.options.onCreate(response); + Ajax.Responders.dispatch('onCreate', this, response); + + this.transport.open(this.method.toUpperCase(), this.url, + this.options.asynchronous); + + if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); + + this.transport.onreadystatechange = this.onStateChange.bind(this); + this.setRequestHeaders(); + + this.body = this.method == 'post' ? (this.options.postBody || params) : null; + this.transport.send(this.body); + + /* Force Firefox to handle ready state 4 for synchronous requests */ + if (!this.options.asynchronous && this.transport.overrideMimeType) + this.onStateChange(); + + } + catch (e) { + this.dispatchException(e); + } + }, + + onStateChange: function() { + var readyState = this.transport.readyState; + if (readyState > 1 && !((readyState == 4) && this._complete)) + this.respondToReadyState(this.transport.readyState); + }, + + setRequestHeaders: function() { + var headers = { + 'X-Requested-With': 'XMLHttpRequest', + 'X-Prototype-Version': Prototype.Version, + 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' + }; + + if (this.method == 'post') { + headers['Content-type'] = this.options.contentType + + (this.options.encoding ? '; charset=' + this.options.encoding : ''); + + /* Force "Connection: close" for older Mozilla browsers to work + * around a bug where XMLHttpRequest sends an incorrect + * Content-length header. See Mozilla Bugzilla #246651. + */ + if (this.transport.overrideMimeType && + (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) + headers['Connection'] = 'close'; + } + + if (typeof this.options.requestHeaders == 'object') { + var extras = this.options.requestHeaders; + + if (Object.isFunction(extras.push)) + for (var i = 0, length = extras.length; i < length; i += 2) + headers[extras[i]] = extras[i+1]; + else + $H(extras).each(function(pair) { headers[pair.key] = pair.value }); + } + + for (var name in headers) + this.transport.setRequestHeader(name, headers[name]); + }, + + success: function() { + var status = this.getStatus(); + return !status || (status >= 200 && status < 300); + }, + + getStatus: function() { + try { + return this.transport.status || 0; + } catch (e) { return 0 } + }, + + respondToReadyState: function(readyState) { + var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); + + if (state == 'Complete') { + try { + this._complete = true; + (this.options['on' + response.status] + || this.options['on' + (this.success() ? 'Success' : 'Failure')] + || Prototype.emptyFunction)(response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + var contentType = response.getHeader('Content-type'); + if (this.options.evalJS == 'force' + || (this.options.evalJS && this.isSameOrigin() && contentType + && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) + this.evalResponse(); + } + + try { + (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); + Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); + } catch (e) { + this.dispatchException(e); + } + + if (state == 'Complete') { + this.transport.onreadystatechange = Prototype.emptyFunction; + } + }, + + isSameOrigin: function() { + var m = this.url.match(/^\s*https?:\/\/[^\/]*/); + return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ + protocol: location.protocol, + domain: document.domain, + port: location.port ? ':' + location.port : '' + })); + }, + + getHeader: function(name) { + try { + return this.transport.getResponseHeader(name) || null; + } catch (e) { return null; } + }, + + evalResponse: function() { + try { + return eval((this.transport.responseText || '').unfilterJSON()); + } catch (e) { + this.dispatchException(e); + } + }, + + dispatchException: function(exception) { + (this.options.onException || Prototype.emptyFunction)(this, exception); + Ajax.Responders.dispatch('onException', this, exception); + } +}); + +Ajax.Request.Events = + ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; + + + + + + + + +Ajax.Response = Class.create({ + initialize: function(request){ + this.request = request; + var transport = this.transport = request.transport, + readyState = this.readyState = transport.readyState; + + if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { + this.status = this.getStatus(); + this.statusText = this.getStatusText(); + this.responseText = String.interpret(transport.responseText); + this.headerJSON = this._getHeaderJSON(); + } + + if(readyState == 4) { + var xml = transport.responseXML; + this.responseXML = Object.isUndefined(xml) ? null : xml; + this.responseJSON = this._getResponseJSON(); + } + }, + + status: 0, + + statusText: '', + + getStatus: Ajax.Request.prototype.getStatus, + + getStatusText: function() { + try { + return this.transport.statusText || ''; + } catch (e) { return '' } + }, + + getHeader: Ajax.Request.prototype.getHeader, + + getAllHeaders: function() { + try { + return this.getAllResponseHeaders(); + } catch (e) { return null } + }, + + getResponseHeader: function(name) { + return this.transport.getResponseHeader(name); + }, + + getAllResponseHeaders: function() { + return this.transport.getAllResponseHeaders(); + }, + + _getHeaderJSON: function() { + var json = this.getHeader('X-JSON'); + if (!json) return null; + json = decodeURIComponent(escape(json)); + try { + return json.evalJSON(this.request.options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + }, + + _getResponseJSON: function() { + var options = this.request.options; + if (!options.evalJSON || (options.evalJSON != 'force' && + !(this.getHeader('Content-type') || '').include('application/json')) || + this.responseText.blank()) + return null; + try { + return this.responseText.evalJSON(options.sanitizeJSON || + !this.request.isSameOrigin()); + } catch (e) { + this.request.dispatchException(e); + } + } +}); + +Ajax.Updater = Class.create(Ajax.Request, { + initialize: function($super, container, url, options) { + this.container = { + success: (container.success || container), + failure: (container.failure || (container.success ? null : container)) + }; + + options = Object.clone(options); + var onComplete = options.onComplete; + options.onComplete = (function(response, json) { + this.updateContent(response.responseText); + if (Object.isFunction(onComplete)) onComplete(response, json); + }).bind(this); + + $super(url, options); + }, + + updateContent: function(responseText) { + var receiver = this.container[this.success() ? 'success' : 'failure'], + options = this.options; + + if (!options.evalScripts) responseText = responseText.stripScripts(); + + if (receiver = $(receiver)) { + if (options.insertion) { + if (Object.isString(options.insertion)) { + var insertion = { }; insertion[options.insertion] = responseText; + receiver.insert(insertion); + } + else options.insertion(receiver, responseText); + } + else receiver.update(responseText); + } + } +}); + +Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { + initialize: function($super, container, url, options) { + $super(options); + this.onComplete = this.options.onComplete; + + this.frequency = (this.options.frequency || 2); + this.decay = (this.options.decay || 1); + + this.updater = { }; + this.container = container; + this.url = url; + + this.start(); + }, + + start: function() { + this.options.onComplete = this.updateComplete.bind(this); + this.onTimerEvent(); + }, + + stop: function() { + this.updater.options.onComplete = undefined; + clearTimeout(this.timer); + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + }, + + updateComplete: function(response) { + if (this.options.decay) { + this.decay = (response.responseText == this.lastText ? + this.decay * this.options.decay : 1); + + this.lastText = response.responseText; + } + this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); + }, + + onTimerEvent: function() { + this.updater = new Ajax.Updater(this.container, this.url, this.options); + } +}); + + + +function $(element) { + if (arguments.length > 1) { + for (var i = 0, elements = [], length = arguments.length; i < length; i++) + elements.push($(arguments[i])); + return elements; + } + if (Object.isString(element)) + element = document.getElementById(element); + return Element.extend(element); +} + +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(Element.extend(query.snapshotItem(i))); + return results; + }; +} + +/*--------------------------------------------------------------------------*/ + +if (!window.Node) var Node = { }; + +if (!Node.ELEMENT_NODE) { + Object.extend(Node, { + ELEMENT_NODE: 1, + ATTRIBUTE_NODE: 2, + TEXT_NODE: 3, + CDATA_SECTION_NODE: 4, + ENTITY_REFERENCE_NODE: 5, + ENTITY_NODE: 6, + PROCESSING_INSTRUCTION_NODE: 7, + COMMENT_NODE: 8, + DOCUMENT_NODE: 9, + DOCUMENT_TYPE_NODE: 10, + DOCUMENT_FRAGMENT_NODE: 11, + NOTATION_NODE: 12 + }); +} + + +(function(global) { + + var SETATTRIBUTE_IGNORES_NAME = (function(){ + var elForm = document.createElement("form"); + var elInput = document.createElement("input"); + var root = document.documentElement; + elInput.setAttribute("name", "test"); + elForm.appendChild(elInput); + root.appendChild(elForm); + var isBuggy = elForm.elements + ? (typeof elForm.elements.test == "undefined") + : null; + root.removeChild(elForm); + elForm = elInput = null; + return isBuggy; + })(); + + var element = global.Element; + global.Element = function(tagName, attributes) { + attributes = attributes || { }; + tagName = tagName.toLowerCase(); + var cache = Element.cache; + if (SETATTRIBUTE_IGNORES_NAME && attributes.name) { + tagName = '<' + tagName + ' name="' + attributes.name + '">'; + delete attributes.name; + return Element.writeAttribute(document.createElement(tagName), attributes); + } + if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName)); + return Element.writeAttribute(cache[tagName].cloneNode(false), attributes); + }; + Object.extend(global.Element, element || { }); + if (element) global.Element.prototype = element.prototype; +})(this); + +Element.cache = { }; +Element.idCounter = 1; + +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 = $(element); + element.style.display = 'none'; + return element; + }, + + show: function(element) { + element = $(element); + element.style.display = ''; + return element; + }, + + remove: function(element) { + element = $(element); + element.parentNode.removeChild(element); + return element; + }, + + update: (function(){ + + var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){ + var el = document.createElement("select"), + isBuggy = true; + el.innerHTML = ""; + if (el.options && el.options[0]) { + isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION"; + } + el = null; + return isBuggy; + })(); + + var TABLE_ELEMENT_INNERHTML_BUGGY = (function(){ + try { + var el = document.createElement("table"); + if (el && el.tBodies) { + el.innerHTML = "test"; + var isBuggy = typeof el.tBodies[0] == "undefined"; + el = null; + return isBuggy; + } + } catch (e) { + return true; + } + })(); + + var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () { + var s = document.createElement("script"), + isBuggy = false; + try { + s.appendChild(document.createTextNode("")); + isBuggy = !s.firstChild || + s.firstChild && s.firstChild.nodeType !== 3; + } catch (e) { + isBuggy = true; + } + s = null; + return isBuggy; + })(); + + function update(element, content) { + element = $(element); + + if (content && content.toElement) + content = content.toElement(); + + if (Object.isElement(content)) + return element.update().insert(content); + + content = Object.toHTML(content); + + var tagName = element.tagName.toUpperCase(); + + if (tagName === 'SCRIPT' && SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING) { + element.text = content; + return element; + } + + if (SELECT_ELEMENT_INNERHTML_BUGGY || TABLE_ELEMENT_INNERHTML_BUGGY) { + if (tagName in Element._insertionTranslations.tags) { + while (element.firstChild) { + element.removeChild(element.firstChild); + } + Element._getContentFromAnonymousElement(tagName, content.stripScripts()) + .each(function(node) { + element.appendChild(node) + }); + } + else { + element.innerHTML = content.stripScripts(); + } + } + else { + element.innerHTML = content.stripScripts(); + } + + content.evalScripts.bind(content).defer(); + return element; + } + + return update; + })(), + + replace: function(element, content) { + element = $(element); + if (content && content.toElement) content = content.toElement(); + else if (!Object.isElement(content)) { + content = Object.toHTML(content); + var range = element.ownerDocument.createRange(); + range.selectNode(element); + content.evalScripts.bind(content).defer(); + content = range.createContextualFragment(content.stripScripts()); + } + element.parentNode.replaceChild(content, element); + return element; + }, + + insert: function(element, insertions) { + element = $(element); + + if (Object.isString(insertions) || Object.isNumber(insertions) || + Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML))) + insertions = {bottom:insertions}; + + var content, insert, tagName, childNodes; + + for (var position in insertions) { + content = insertions[position]; + position = position.toLowerCase(); + insert = Element._insertionTranslations[position]; + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + insert(element, content); + continue; + } + + content = Object.toHTML(content); + + tagName = ((position == 'before' || position == 'after') + ? element.parentNode : element).tagName.toUpperCase(); + + childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + + if (position == 'top' || position == 'after') childNodes.reverse(); + childNodes.each(insert.curry(element)); + + content.evalScripts.bind(content).defer(); + } + + return element; + }, + + wrap: function(element, wrapper, attributes) { + element = $(element); + if (Object.isElement(wrapper)) + $(wrapper).writeAttribute(attributes || { }); + else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes); + else wrapper = new Element('div', wrapper); + if (element.parentNode) + element.parentNode.replaceChild(wrapper, element); + wrapper.appendChild(element); + return wrapper; + }, + + inspect: function(element) { + element = $(element); + var result = '<' + element.tagName.toLowerCase(); + $H({'id': 'id', 'className': 'class'}).each(function(pair) { + var property = pair.first(), attribute = pair.last(); + var value = (element[property] || '').toString(); + if (value) result += ' ' + attribute + '=' + value.inspect(true); + }); + return result + '>'; + }, + + recursivelyCollect: function(element, property) { + element = $(element); + var elements = []; + while (element = element[property]) + if (element.nodeType == 1) + elements.push(Element.extend(element)); + return elements; + }, + + ancestors: function(element) { + return Element.recursivelyCollect(element, 'parentNode'); + }, + + descendants: function(element) { + return Element.select(element, "*"); + }, + + firstDescendant: function(element) { + element = $(element).firstChild; + while (element && element.nodeType != 1) element = element.nextSibling; + return $(element); + }, + + immediateDescendants: function(element) { + if (!(element = $(element).firstChild)) return []; + while (element && element.nodeType != 1) element = element.nextSibling; + if (element) return [element].concat($(element).nextSiblings()); + return []; + }, + + previousSiblings: function(element) { + return Element.recursivelyCollect(element, 'previousSibling'); + }, + + nextSiblings: function(element) { + return Element.recursivelyCollect(element, 'nextSibling'); + }, + + siblings: function(element) { + element = $(element); + return Element.previousSiblings(element).reverse() + .concat(Element.nextSiblings(element)); + }, + + match: function(element, selector) { + if (Object.isString(selector)) + 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(element); + return Object.isNumber(expression) ? ancestors[expression] : + Selector.findElement(ancestors, expression, index); + }, + + down: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return Element.firstDescendant(element); + return Object.isNumber(expression) ? Element.descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + }, + + previous: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element)); + var previousSiblings = Element.previousSiblings(element); + return Object.isNumber(expression) ? previousSiblings[expression] : + Selector.findElement(previousSiblings, expression, index); + }, + + next: function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element)); + var nextSiblings = Element.nextSiblings(element); + return Object.isNumber(expression) ? nextSiblings[expression] : + Selector.findElement(nextSiblings, expression, index); + }, + + + select: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element, args); + }, + + adjacent: function(element) { + var args = Array.prototype.slice.call(arguments, 1); + return Selector.findChildElements(element.parentNode, args).without(element); + }, + + identify: function(element) { + element = $(element); + var id = Element.readAttribute(element, 'id'); + if (id) return id; + do { id = 'anonymous_element_' + Element.idCounter++ } while ($(id)); + Element.writeAttribute(element, 'id', id); + return id; + }, + + readAttribute: function(element, name) { + element = $(element); + if (Prototype.Browser.IE) { + var t = Element._attributeTranslations.read; + if (t.values[name]) return t.values[name](element, name); + if (t.names[name]) name = t.names[name]; + if (name.include(':')) { + return (!element.attributes || !element.attributes[name]) ? null : + element.attributes[name].value; + } + } + return element.getAttribute(name); + }, + + writeAttribute: function(element, name, value) { + element = $(element); + var attributes = { }, t = Element._attributeTranslations.write; + + if (typeof name == 'object') attributes = name; + else attributes[name] = Object.isUndefined(value) ? true : value; + + for (var attr in attributes) { + name = t.names[attr] || attr; + value = attributes[attr]; + if (t.values[attr]) name = t.values[attr](element, value); + if (value === false || value === null) + element.removeAttribute(name); + else if (value === true) + element.setAttribute(name, name); + else element.setAttribute(name, value); + } + return element; + }, + + getHeight: function(element) { + return Element.getDimensions(element).height; + }, + + getWidth: function(element) { + return Element.getDimensions(element).width; + }, + + classNames: function(element) { + return new Element.ClassNames(element); + }, + + hasClassName: function(element, className) { + if (!(element = $(element))) return; + var elementClassName = element.className; + return (elementClassName.length > 0 && (elementClassName == className || + new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName))); + }, + + addClassName: function(element, className) { + if (!(element = $(element))) return; + if (!Element.hasClassName(element, className)) + element.className += (element.className ? ' ' : '') + className; + return element; + }, + + removeClassName: function(element, className) { + if (!(element = $(element))) return; + element.className = element.className.replace( + new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip(); + return element; + }, + + toggleClassName: function(element, className) { + if (!(element = $(element))) return; + return Element[Element.hasClassName(element, className) ? + 'removeClassName' : 'addClassName'](element, className); + }, + + 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; + }, + + empty: function(element) { + return $(element).innerHTML.blank(); + }, + + descendantOf: function(element, ancestor) { + element = $(element), ancestor = $(ancestor); + + if (element.compareDocumentPosition) + return (element.compareDocumentPosition(ancestor) & 8) === 8; + + if (ancestor.contains) + return ancestor.contains(element) && ancestor !== element; + + while (element = element.parentNode) + if (element == ancestor) return true; + + return false; + }, + + scrollTo: function(element) { + element = $(element); + var pos = Element.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 || value == 'auto') { + 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) { + element = $(element); + var elementStyle = element.style, match; + if (Object.isString(styles)) { + element.style.cssText += ';' + styles; + return styles.include('opacity') ? + element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element; + } + for (var property in styles) + if (property == 'opacity') element.setOpacity(styles[property]); + else + elementStyle[(property == 'float' || property == 'cssFloat') ? + (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') : + property] = styles[property]; + + return element; + }, + + setOpacity: function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + return element; + }, + + getDimensions: function(element) { + element = $(element); + var display = Element.getStyle(element, 'display'); + if (display != 'none' && display != null) // Safari bug + return {width: element.offsetWidth, height: element.offsetHeight}; + + var els = element.style; + var originalVisibility = els.visibility; + var originalPosition = els.position; + var originalDisplay = els.display; + els.visibility = 'hidden'; + if (originalPosition != 'fixed') // Switching fixed to absolute causes issues in Safari + 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}; + }, + + makePositioned: function(element) { + element = $(element); + var pos = Element.getStyle(element, 'position'); + if (pos == 'static' || !pos) { + element._madePositioned = true; + element.style.position = 'relative'; + if (Prototype.Browser.Opera) { + element.style.top = 0; + element.style.left = 0; + } + } + return element; + }, + + undoPositioned: function(element) { + element = $(element); + if (element._madePositioned) { + element._madePositioned = undefined; + element.style.position = + element.style.top = + element.style.left = + element.style.bottom = + element.style.right = ''; + } + return element; + }, + + makeClipping: function(element) { + element = $(element); + if (element._overflow) return element; + element._overflow = Element.getStyle(element, 'overflow') || 'auto'; + if (element._overflow !== 'hidden') + element.style.overflow = 'hidden'; + return element; + }, + + undoClipping: function(element) { + element = $(element); + if (!element._overflow) return element; + element.style.overflow = element._overflow == 'auto' ? '' : element._overflow; + element._overflow = null; + return element; + }, + + cumulativeOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + positionedOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + element = element.offsetParent; + if (element) { + if (element.tagName.toUpperCase() == 'BODY') break; + var p = Element.getStyle(element, 'position'); + if (p !== 'static') break; + } + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + absolutize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'absolute') return element; + + var offsets = Element.positionedOffset(element); + var top = offsets[1]; + var left = offsets[0]; + var width = element.clientWidth; + var height = element.clientHeight; + + element._originalLeft = left - parseFloat(element.style.left || 0); + element._originalTop = top - parseFloat(element.style.top || 0); + element._originalWidth = element.style.width; + element._originalHeight = element.style.height; + + element.style.position = 'absolute'; + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.width = width + 'px'; + element.style.height = height + 'px'; + return element; + }, + + relativize: function(element) { + element = $(element); + if (Element.getStyle(element, 'position') == 'relative') return element; + + element.style.position = 'relative'; + var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); + var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); + + element.style.top = top + 'px'; + element.style.left = left + 'px'; + element.style.height = element._originalHeight; + element.style.width = element._originalWidth; + return element; + }, + + cumulativeScrollOffset: function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.scrollTop || 0; + valueL += element.scrollLeft || 0; + element = element.parentNode; + } while (element); + return Element._returnOffset(valueL, valueT); + }, + + getOffsetParent: function(element) { + if (element.offsetParent) return $(element.offsetParent); + if (element == document.body) return $(element); + + while ((element = element.parentNode) && element != document.body) + if (Element.getStyle(element, 'position') != 'static') + return $(element); + + return $(document.body); + }, + + viewportOffset: function(forElement) { + var valueT = 0, valueL = 0; + + var element = forElement; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + + if (element.offsetParent == document.body && + Element.getStyle(element, 'position') == 'absolute') break; + + } while (element = element.offsetParent); + + element = forElement; + do { + if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) { + valueT -= element.scrollTop || 0; + valueL -= element.scrollLeft || 0; + } + } while (element = element.parentNode); + + return Element._returnOffset(valueL, valueT); + }, + + clonePosition: function(element, source) { + var options = Object.extend({ + setLeft: true, + setTop: true, + setWidth: true, + setHeight: true, + offsetTop: 0, + offsetLeft: 0 + }, arguments[2] || { }); + + source = $(source); + var p = Element.viewportOffset(source); + + element = $(element); + var delta = [0, 0]; + var parent = null; + if (Element.getStyle(element, 'position') == 'absolute') { + parent = Element.getOffsetParent(element); + delta = Element.viewportOffset(parent); + } + + if (parent == document.body) { + delta[0] -= document.body.offsetLeft; + delta[1] -= document.body.offsetTop; + } + + if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; + if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; + if (options.setWidth) element.style.width = source.offsetWidth + 'px'; + if (options.setHeight) element.style.height = source.offsetHeight + 'px'; + return element; + } +}; + +Object.extend(Element.Methods, { + getElementsBySelector: Element.Methods.select, + + childElements: Element.Methods.immediateDescendants +}); + +Element._attributeTranslations = { + write: { + names: { + className: 'class', + htmlFor: 'for' + }, + values: { } + } +}; + +if (Prototype.Browser.Opera) { + Element.Methods.getStyle = Element.Methods.getStyle.wrap( + function(proceed, element, style) { + switch (style) { + case 'left': case 'top': case 'right': case 'bottom': + if (proceed(element, 'position') === 'static') return null; + case 'height': case 'width': + if (!Element.visible(element)) return null; + + var dim = parseInt(proceed(element, style), 10); + + if (dim !== element['offset' + style.capitalize()]) + return dim + 'px'; + + var properties; + if (style === 'height') { + properties = ['border-top-width', 'padding-top', + 'padding-bottom', 'border-bottom-width']; + } + else { + properties = ['border-left-width', 'padding-left', + 'padding-right', 'border-right-width']; + } + return properties.inject(dim, function(memo, property) { + var val = proceed(element, property); + return val === null ? memo : memo - parseInt(val, 10); + }) + 'px'; + default: return proceed(element, style); + } + } + ); + + Element.Methods.readAttribute = Element.Methods.readAttribute.wrap( + function(proceed, element, attribute) { + if (attribute === 'title') return element.title; + return proceed(element, attribute); + } + ); +} + +else if (Prototype.Browser.IE) { + Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return $(document.body) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + + $w('positionedOffset viewportOffset').each(function(method) { + Element.Methods[method] = Element.Methods[method].wrap( + function(proceed, element) { + element = $(element); + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + var position = element.getStyle('position'); + if (position !== 'static') return proceed(element); + var offsetParent = element.getOffsetParent(); + if (offsetParent && offsetParent.getStyle('position') === 'fixed') + offsetParent.setStyle({ zoom: 1 }); + element.setStyle({ position: 'relative' }); + var value = proceed(element); + element.setStyle({ position: position }); + return value; + } + ); + }); + + Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap( + function(proceed, element) { + try { element.offsetParent } + catch(e) { return Element._returnOffset(0,0) } + return proceed(element); + } + ); + + 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) { + function stripAlpha(filter){ + return filter.replace(/alpha\([^\)]*\)/gi,''); + } + element = $(element); + var currentStyle = element.currentStyle; + if ((currentStyle && !currentStyle.hasLayout) || + (!currentStyle && element.style.zoom == 'normal')) + element.style.zoom = 1; + + var filter = element.getStyle('filter'), style = element.style; + if (value == 1 || value === '') { + (filter = stripAlpha(filter)) ? + style.filter = filter : style.removeAttribute('filter'); + return element; + } else if (value < 0.00001) value = 0; + style.filter = stripAlpha(filter) + + 'alpha(opacity=' + (value * 100) + ')'; + return element; + }; + + Element._attributeTranslations = (function(){ + + var classProp = 'className'; + var forProp = 'for'; + + var el = document.createElement('div'); + + el.setAttribute(classProp, 'x'); + + if (el.className !== 'x') { + el.setAttribute('class', 'x'); + if (el.className === 'x') { + classProp = 'class'; + } + } + el = null; + + el = document.createElement('label'); + el.setAttribute(forProp, 'x'); + if (el.htmlFor !== 'x') { + el.setAttribute('htmlFor', 'x'); + if (el.htmlFor === 'x') { + forProp = 'htmlFor'; + } + } + el = null; + + return { + read: { + names: { + 'class': classProp, + 'className': classProp, + 'for': forProp, + 'htmlFor': forProp + }, + values: { + _getAttr: function(element, attribute) { + return element.getAttribute(attribute); + }, + _getAttr2: function(element, attribute) { + return element.getAttribute(attribute, 2); + }, + _getAttrNode: function(element, attribute) { + var node = element.getAttributeNode(attribute); + return node ? node.value : ""; + }, + _getEv: (function(){ + + var el = document.createElement('div'); + el.onclick = Prototype.emptyFunction; + var value = el.getAttribute('onclick'); + var f; + + if (String(value).indexOf('{') > -1) { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + attribute = attribute.toString(); + attribute = attribute.split('{')[1]; + attribute = attribute.split('}')[0]; + return attribute.strip(); + }; + } + else if (value === '') { + f = function(element, attribute) { + attribute = element.getAttribute(attribute); + if (!attribute) return null; + return attribute.strip(); + }; + } + el = null; + return f; + })(), + _flag: function(element, attribute) { + return $(element).hasAttribute(attribute) ? attribute : null; + }, + style: function(element) { + return element.style.cssText.toLowerCase(); + }, + title: function(element) { + return element.title; + } + } + } + } + })(); + + Element._attributeTranslations.write = { + names: Object.extend({ + cellpadding: 'cellPadding', + cellspacing: 'cellSpacing' + }, Element._attributeTranslations.read.names), + values: { + checked: function(element, value) { + element.checked = !!value; + }, + + style: function(element, value) { + element.style.cssText = value ? value : ''; + } + } + }; + + Element._attributeTranslations.has = {}; + + $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' + + 'encType maxLength readOnly longDesc frameBorder').each(function(attr) { + Element._attributeTranslations.write.names[attr.toLowerCase()] = attr; + Element._attributeTranslations.has[attr.toLowerCase()] = attr; + }); + + (function(v) { + Object.extend(v, { + href: v._getAttr2, + src: v._getAttr2, + type: v._getAttr, + action: v._getAttrNode, + disabled: v._flag, + checked: v._flag, + readonly: v._flag, + multiple: v._flag, + onload: v._getEv, + onunload: v._getEv, + onclick: v._getEv, + ondblclick: v._getEv, + onmousedown: v._getEv, + onmouseup: v._getEv, + onmouseover: v._getEv, + onmousemove: v._getEv, + onmouseout: v._getEv, + onfocus: v._getEv, + onblur: v._getEv, + onkeypress: v._getEv, + onkeydown: v._getEv, + onkeyup: v._getEv, + onsubmit: v._getEv, + onreset: v._getEv, + onselect: v._getEv, + onchange: v._getEv + }); + })(Element._attributeTranslations.read.values); + + if (Prototype.BrowserFeatures.ElementExtensions) { + (function() { + function _descendants(element) { + var nodes = element.getElementsByTagName('*'), results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName !== "!") // Filter out comment nodes. + results.push(node); + return results; + } + + Element.Methods.down = function(element, expression, index) { + element = $(element); + if (arguments.length == 1) return element.firstDescendant(); + return Object.isNumber(expression) ? _descendants(element)[expression] : + Element.select(element, expression)[index || 0]; + } + })(); + } + +} + +else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1) ? 0.999999 : + (value === '') ? '' : (value < 0.00001) ? 0 : value; + return element; + }; +} + +else if (Prototype.Browser.WebKit) { + Element.Methods.setOpacity = function(element, value) { + element = $(element); + element.style.opacity = (value == 1 || value === '') ? '' : + (value < 0.00001) ? 0 : value; + + if (value == 1) + if(element.tagName.toUpperCase() == 'IMG' && element.width) { + element.width++; element.width--; + } else try { + var n = document.createTextNode(' '); + element.appendChild(n); + element.removeChild(n); + } catch (e) { } + + return element; + }; + + Element.Methods.cumulativeOffset = function(element) { + var valueT = 0, valueL = 0; + do { + valueT += element.offsetTop || 0; + valueL += element.offsetLeft || 0; + if (element.offsetParent == document.body) + if (Element.getStyle(element, 'position') == 'absolute') break; + + element = element.offsetParent; + } while (element); + + return Element._returnOffset(valueL, valueT); + }; +} + +if ('outerHTML' in document.documentElement) { + Element.Methods.replace = function(element, content) { + element = $(element); + + if (content && content.toElement) content = content.toElement(); + if (Object.isElement(content)) { + element.parentNode.replaceChild(content, element); + return element; + } + + content = Object.toHTML(content); + var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); + + if (Element._insertionTranslations.tags[tagName]) { + var nextSibling = element.next(); + var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts()); + parent.removeChild(element); + if (nextSibling) + fragments.each(function(node) { parent.insertBefore(node, nextSibling) }); + else + fragments.each(function(node) { parent.appendChild(node) }); + } + else element.outerHTML = content.stripScripts(); + + content.evalScripts.bind(content).defer(); + return element; + }; +} + +Element._returnOffset = function(l, t) { + var result = [l, t]; + result.left = l; + result.top = t; + return result; +}; + +Element._getContentFromAnonymousElement = function(tagName, html) { + var div = new Element('div'), t = Element._insertionTranslations.tags[tagName]; + if (t) { + div.innerHTML = t[0] + html + t[1]; + t[2].times(function() { div = div.firstChild }); + } else div.innerHTML = html; + return $A(div.childNodes); +}; + +Element._insertionTranslations = { + before: function(element, node) { + element.parentNode.insertBefore(node, element); + }, + top: function(element, node) { + element.insertBefore(node, element.firstChild); + }, + bottom: function(element, node) { + element.appendChild(node); + }, + after: function(element, node) { + element.parentNode.insertBefore(node, element.nextSibling); + }, + tags: { + TABLE: ['', '
    ', 1], + TBODY: ['', '
    ', 2], + TR: ['', '
    ', 3], + TD: ['
    ', '
    ', 4], + SELECT: ['', 1] + } +}; + +(function() { + var tags = Element._insertionTranslations.tags; + Object.extend(tags, { + THEAD: tags.TBODY, + TFOOT: tags.TBODY, + TH: tags.TD + }); +})(); + +Element.Methods.Simulated = { + hasAttribute: function(element, attribute) { + attribute = Element._attributeTranslations.has[attribute] || attribute; + var node = $(element).getAttributeNode(attribute); + return !!(node && node.specified); + } +}; + +Element.Methods.ByTag = { }; + +Object.extend(Element, Element.Methods); + +(function(div) { + + if (!Prototype.BrowserFeatures.ElementExtensions && div['__proto__']) { + window.HTMLElement = { }; + window.HTMLElement.prototype = div['__proto__']; + Prototype.BrowserFeatures.ElementExtensions = true; + } + + div = null; + +})(document.createElement('div')) + +Element.extend = (function() { + + function checkDeficiency(tagName) { + if (typeof window.Element != 'undefined') { + var proto = window.Element.prototype; + if (proto) { + var id = '_' + (Math.random()+'').slice(2); + var el = document.createElement(tagName); + proto[id] = 'x'; + var isBuggy = (el[id] !== 'x'); + delete proto[id]; + el = null; + return isBuggy; + } + } + return false; + } + + function extendElementWith(element, methods) { + for (var property in methods) { + var value = methods[property]; + if (Object.isFunction(value) && !(property in element)) + element[property] = value.methodize(); + } + } + + var HTMLOBJECTELEMENT_PROTOTYPE_BUGGY = checkDeficiency('object'); + + if (Prototype.BrowserFeatures.SpecificElementExtensions) { + if (HTMLOBJECTELEMENT_PROTOTYPE_BUGGY) { + return function(element) { + if (element && typeof element._extendedByPrototype == 'undefined') { + var t = element.tagName; + if (t && (/^(?:object|applet|embed)$/i.test(t))) { + extendElementWith(element, Element.Methods); + extendElementWith(element, Element.Methods.Simulated); + extendElementWith(element, Element.Methods.ByTag[t.toUpperCase()]); + } + } + return element; + } + } + return Prototype.K; + } + + var Methods = { }, ByTag = Element.Methods.ByTag; + + var extend = Object.extend(function(element) { + if (!element || typeof element._extendedByPrototype != 'undefined' || + element.nodeType != 1 || element == window) return element; + + var methods = Object.clone(Methods), + tagName = element.tagName.toUpperCase(); + + if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]); + + extendElementWith(element, methods); + + element._extendedByPrototype = Prototype.emptyFunction; + return element; + + }, { + refresh: function() { + if (!Prototype.BrowserFeatures.ElementExtensions) { + Object.extend(Methods, Element.Methods); + Object.extend(Methods, Element.Methods.Simulated); + } + } + }); + + extend.refresh(); + return extend; +})(); + +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, { + "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 (Object.isArray(tagName)) 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; + for (var property in methods) { + var value = methods[property]; + if (!Object.isFunction(value)) continue; + if (!onlyIfAbsent || !(property in destination)) + destination[property] = value.methodize(); + } + } + + 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]; + + var element = document.createElement(tagName); + var proto = element['__proto__'] || element.constructor.prototype; + element = null; + return proto; + } + + var elementPrototype = window.HTMLElement ? HTMLElement.prototype : + Element.prototype; + + if (F.ElementExtensions) { + copy(Element.Methods, elementPrototype); + copy(Element.Methods.Simulated, elementPrototype, true); + } + + if (F.SpecificElementExtensions) { + for (var tag in Element.Methods.ByTag) { + var klass = findDOMClass(tag); + if (Object.isUndefined(klass)) continue; + copy(T[tag], klass.prototype); + } + } + + Object.extend(Element, Element.Methods); + delete Element.ByTag; + + if (Element.extend.refresh) Element.extend.refresh(); + Element.cache = { }; +}; + + +document.viewport = { + + getDimensions: function() { + return { width: this.getWidth(), height: this.getHeight() }; + }, + + getScrollOffsets: function() { + return Element._returnOffset( + window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, + window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop); + } +}; + +(function(viewport) { + var B = Prototype.Browser, doc = document, element, property = {}; + + function getRootElement() { + if (B.WebKit && !doc.evaluate) + return document; + + if (B.Opera && window.parseFloat(window.opera.version()) < 9.5) + return document.body; + + return document.documentElement; + } + + function define(D) { + if (!element) element = getRootElement(); + + property[D] = 'client' + D; + + viewport['get' + D] = function() { return element[property[D]] }; + return viewport['get' + D](); + } + + viewport.getWidth = define.curry('Width'); + + viewport.getHeight = define.curry('Height'); +})(document.viewport); + + +Element.Storage = { + UID: 1 +}; + +Element.addMethods({ + getStorage: function(element) { + if (!(element = $(element))) return; + + var uid; + if (element === window) { + uid = 0; + } else { + if (typeof element._prototypeUID === "undefined") + element._prototypeUID = [Element.Storage.UID++]; + uid = element._prototypeUID[0]; + } + + if (!Element.Storage[uid]) + Element.Storage[uid] = $H(); + + return Element.Storage[uid]; + }, + + store: function(element, key, value) { + if (!(element = $(element))) return; + + if (arguments.length === 2) { + Element.getStorage(element).update(key); + } else { + Element.getStorage(element).set(key, value); + } + + return element; + }, + + retrieve: function(element, key, defaultValue) { + if (!(element = $(element))) return; + var hash = Element.getStorage(element), value = hash.get(key); + + if (Object.isUndefined(value)) { + hash.set(key, defaultValue); + value = defaultValue; + } + + return value; + }, + + clone: function(element, deep) { + if (!(element = $(element))) return; + var clone = element.cloneNode(deep); + clone._prototypeUID = void 0; + if (deep) { + var descendants = Element.select(clone, '*'), + i = descendants.length; + while (i--) { + descendants[i]._prototypeUID = void 0; + } + } + return Element.extend(clone); + } +}); +/* Portions of the Selector class are derived from Jack Slocum's DomQuery, + * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style + * license. Please see http://www.yui-ext.com/ for more information. */ + +var Selector = Class.create({ + initialize: function(expression) { + this.expression = expression.strip(); + + if (this.shouldUseSelectorsAPI()) { + this.mode = 'selectorsAPI'; + } else if (this.shouldUseXPath()) { + this.mode = 'xpath'; + this.compileXPathMatcher(); + } else { + this.mode = "normal"; + this.compileMatcher(); + } + + }, + + shouldUseXPath: (function() { + + var IS_DESCENDANT_SELECTOR_BUGGY = (function(){ + var isBuggy = false; + if (document.evaluate && window.XPathResult) { + var el = document.createElement('div'); + el.innerHTML = '
    '; + + var xpath = ".//*[local-name()='ul' or local-name()='UL']" + + "//*[local-name()='li' or local-name()='LI']"; + + var result = document.evaluate(xpath, el, null, + XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); + + isBuggy = (result.snapshotLength !== 2); + el = null; + } + return isBuggy; + })(); + + return function() { + if (!Prototype.BrowserFeatures.XPath) return false; + + var e = this.expression; + + if (Prototype.Browser.WebKit && + (e.include("-of-type") || e.include(":empty"))) + return false; + + if ((/(\[[\w-]*?:|:checked)/).test(e)) + return false; + + if (IS_DESCENDANT_SELECTOR_BUGGY) return false; + + return true; + } + + })(), + + shouldUseSelectorsAPI: function() { + if (!Prototype.BrowserFeatures.SelectorsAPI) return false; + + if (Selector.CASE_INSENSITIVE_CLASS_NAMES) return false; + + if (!Selector._div) Selector._div = new Element('div'); + + try { + Selector._div.querySelector(this.expression); + } catch(e) { + return false; + } + + return true; + }, + + compileMatcher: function() { + var e = this.expression, ps = Selector.patterns, h = Selector.handlers, + c = Selector.criteria, le, p, m, len = ps.length, name; + + if (Selector._cache[e]) { + this.matcher = Selector._cache[e]; + return; + } + + this.matcher = ["this.matcher = function(root) {", + "var r = root, h = Selector.handlers, c = false, n;"]; + + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i"; + } +}); + +if (Prototype.BrowserFeatures.SelectorsAPI && + document.compatMode === 'BackCompat') { + Selector.CASE_INSENSITIVE_CLASS_NAMES = (function(){ + var div = document.createElement('div'), + span = document.createElement('span'); + + div.id = "prototype_test_id"; + span.className = 'Test'; + div.appendChild(span); + var isIgnored = (div.querySelector('#prototype_test_id .test') !== null); + div = span = null; + return isIgnored; + })(); +} + +Object.extend(Selector, { + _cache: { }, + + xpath: { + descendant: "//*", + child: "/*", + adjacent: "/following-sibling::*[1]", + laterSibling: '/following-sibling::*', + tagName: function(m) { + if (m[1] == '*') return ''; + return "[local-name()='" + m[1].toLowerCase() + + "' or local-name()='" + m[1].toUpperCase() + "']"; + }, + className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", + id: "[@id='#{1}']", + attrPresence: function(m) { + m[1] = m[1].toLowerCase(); + return new Template("[@#{1}]").evaluate(m); + }, + attr: function(m) { + m[1] = m[1].toLowerCase(); + m[3] = m[5] || m[6]; + return new Template(Selector.xpath.operators[m[2]]).evaluate(m); + }, + pseudo: function(m) { + var h = Selector.xpath.pseudos[m[1]]; + if (!h) return ''; + if (Object.isFunction(h)) return h(m); + return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m); + }, + operators: { + '=': "[@#{1}='#{3}']", + '!=': "[@#{1}!='#{3}']", + '^=': "[starts-with(@#{1}, '#{3}')]", + '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", + '*=': "[contains(@#{1}, '#{3}')]", + '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", + '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" + }, + pseudos: { + 'first-child': '[not(preceding-sibling::*)]', + 'last-child': '[not(following-sibling::*)]', + 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', + 'empty': "[count(*) = 0 and (count(text()) = 0)]", + 'checked': "[@checked]", + 'disabled': "[(@disabled) and (@type!='hidden')]", + 'enabled': "[not(@disabled) and (@type!='hidden')]", + 'not': function(m) { + var e = m[6], p = Selector.patterns, + x = Selector.xpath, le, v, len = p.length, name; + + var exclusion = []; + while (e && le != e && (/\S/).test(e)) { + le = e; + for (var i = 0; i= 0)]"; + return new Template(predicate).evaluate({ + fragment: fragment, a: a, b: b }); + } + } + } + }, + + criteria: { + tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', + className: 'n = h.className(n, r, "#{1}", c); c = false;', + id: 'n = h.id(n, r, "#{1}", c); c = false;', + attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', + attr: function(m) { + m[3] = (m[5] || m[6]); + return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); + }, + pseudo: function(m) { + if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); + return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); + }, + descendant: 'c = "descendant";', + child: 'c = "child";', + adjacent: 'c = "adjacent";', + laterSibling: 'c = "laterSibling";' + }, + + patterns: [ + { name: 'laterSibling', re: /^\s*~\s*/ }, + { name: 'child', re: /^\s*>\s*/ }, + { name: 'adjacent', re: /^\s*\+\s*/ }, + { name: 'descendant', re: /^\s/ }, + + { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, + { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, + { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, + { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, + { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, + { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } + ], + + assertions: { + tagName: function(element, matches) { + return matches[1].toUpperCase() == element.tagName.toUpperCase(); + }, + + className: function(element, matches) { + return Element.hasClassName(element, matches[1]); + }, + + id: function(element, matches) { + return element.id === matches[1]; + }, + + attrPresence: function(element, matches) { + return Element.hasAttribute(element, matches[1]); + }, + + attr: function(element, matches) { + var nodeValue = Element.readAttribute(element, matches[1]); + return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]); + } + }, + + handlers: { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + a.push(node); + return a; + }, + + mark: function(nodes) { + var _true = Prototype.emptyFunction; + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = _true; + return nodes; + }, + + unmark: (function(){ + + var PROPERTIES_ATTRIBUTES_MAP = (function(){ + var el = document.createElement('div'), + isBuggy = false, + propName = '_countedByPrototype', + value = 'x' + el[propName] = value; + isBuggy = (el.getAttribute(propName) === value); + el = null; + return isBuggy; + })(); + + return PROPERTIES_ATTRIBUTES_MAP ? + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node.removeAttribute('_countedByPrototype'); + return nodes; + } : + function(nodes) { + for (var i = 0, node; node = nodes[i]; i++) + node._countedByPrototype = void 0; + return nodes; + } + })(), + + index: function(parentNode, reverse, ofType) { + parentNode._countedByPrototype = Prototype.emptyFunction; + if (reverse) { + for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { + var node = nodes[i]; + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + } else { + for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) + if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; + } + }, + + unique: function(nodes) { + if (nodes.length == 0) return nodes; + var results = [], n; + for (var i = 0, l = nodes.length; i < l; i++) + if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { + n._countedByPrototype = Prototype.emptyFunction; + results.push(Element.extend(n)); + } + return Selector.handlers.unmark(results); + }, + + descendant: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName('*')); + return results; + }, + + child: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) { + for (var j = 0, child; child = node.childNodes[j]; j++) + if (child.nodeType == 1 && child.tagName != '!') results.push(child); + } + return results; + }, + + adjacent: function(nodes) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + var next = this.nextElementSibling(node); + if (next) results.push(next); + } + return results; + }, + + laterSibling: function(nodes) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + h.concat(results, Element.nextSiblings(node)); + return results; + }, + + nextElementSibling: function(node) { + while (node = node.nextSibling) + if (node.nodeType == 1) return node; + return null; + }, + + previousElementSibling: function(node) { + while (node = node.previousSibling) + if (node.nodeType == 1) return node; + return null; + }, + + tagName: function(nodes, root, tagName, combinator) { + var uTagName = tagName.toUpperCase(); + var results = [], h = Selector.handlers; + if (nodes) { + if (combinator) { + if (combinator == "descendant") { + for (var i = 0, node; node = nodes[i]; i++) + h.concat(results, node.getElementsByTagName(tagName)); + return results; + } else nodes = this[combinator](nodes); + if (tagName == "*") return nodes; + } + for (var i = 0, node; node = nodes[i]; i++) + if (node.tagName.toUpperCase() === uTagName) results.push(node); + return results; + } else return root.getElementsByTagName(tagName); + }, + + id: function(nodes, root, id, combinator) { + var targetNode = $(id), h = Selector.handlers; + + if (root == document) { + if (!targetNode) return []; + if (!nodes) return [targetNode]; + } else { + if (!root.sourceIndex || root.sourceIndex < 1) { + var nodes = root.getElementsByTagName('*'); + for (var j = 0, node; node = nodes[j]; j++) { + if (node.id === id) return [node]; + } + } + } + + if (nodes) { + if (combinator) { + if (combinator == 'child') { + for (var i = 0, node; node = nodes[i]; i++) + if (targetNode.parentNode == node) return [targetNode]; + } else if (combinator == 'descendant') { + for (var i = 0, node; node = nodes[i]; i++) + if (Element.descendantOf(targetNode, node)) return [targetNode]; + } else if (combinator == 'adjacent') { + for (var i = 0, node; node = nodes[i]; i++) + if (Selector.handlers.previousElementSibling(targetNode) == node) + return [targetNode]; + } else nodes = h[combinator](nodes); + } + for (var i = 0, node; node = nodes[i]; i++) + if (node == targetNode) return [targetNode]; + return []; + } + return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; + }, + + className: function(nodes, root, className, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + return Selector.handlers.byClassName(nodes, root, className); + }, + + byClassName: function(nodes, root, className) { + if (!nodes) nodes = Selector.handlers.descendant([root]); + var needle = ' ' + className + ' '; + for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { + nodeClassName = node.className; + if (nodeClassName.length == 0) continue; + if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) + results.push(node); + } + return results; + }, + + attrPresence: function(nodes, root, attr, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var results = []; + for (var i = 0, node; node = nodes[i]; i++) + if (Element.hasAttribute(node, attr)) results.push(node); + return results; + }, + + attr: function(nodes, root, attr, value, operator, combinator) { + if (!nodes) nodes = root.getElementsByTagName("*"); + if (nodes && combinator) nodes = this[combinator](nodes); + var handler = Selector.operators[operator], results = []; + for (var i = 0, node; node = nodes[i]; i++) { + var nodeValue = Element.readAttribute(node, attr); + if (nodeValue === null) continue; + if (handler(nodeValue, value)) results.push(node); + } + return results; + }, + + pseudo: function(nodes, name, value, root, combinator) { + if (nodes && combinator) nodes = this[combinator](nodes); + if (!nodes) nodes = root.getElementsByTagName("*"); + return Selector.pseudos[name](nodes, value, root); + } + }, + + pseudos: { + 'first-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.previousElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'last-child': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (Selector.handlers.nextElementSibling(node)) continue; + results.push(node); + } + return results; + }, + 'only-child': function(nodes, value, root) { + var h = Selector.handlers; + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) + results.push(node); + return results; + }, + 'nth-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root); + }, + 'nth-last-child': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true); + }, + 'nth-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, false, true); + }, + 'nth-last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, formula, root, true, true); + }, + 'first-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, false, true); + }, + 'last-of-type': function(nodes, formula, root) { + return Selector.pseudos.nth(nodes, "1", root, true, true); + }, + 'only-of-type': function(nodes, formula, root) { + var p = Selector.pseudos; + return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); + }, + + getIndices: function(a, b, total) { + if (a == 0) return b > 0 ? [b] : []; + return $R(1, total).inject([], function(memo, i) { + if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); + return memo; + }); + }, + + nth: function(nodes, formula, root, reverse, ofType) { + if (nodes.length == 0) return []; + if (formula == 'even') formula = '2n+0'; + if (formula == 'odd') formula = '2n+1'; + var h = Selector.handlers, results = [], indexed = [], m; + h.mark(nodes); + for (var i = 0, node; node = nodes[i]; i++) { + if (!node.parentNode._countedByPrototype) { + h.index(node.parentNode, reverse, ofType); + indexed.push(node.parentNode); + } + } + if (formula.match(/^\d+$/)) { // just a number + formula = Number(formula); + for (var i = 0, node; node = nodes[i]; i++) + if (node.nodeIndex == formula) results.push(node); + } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b + if (m[1] == "-") m[1] = -1; + var a = m[1] ? Number(m[1]) : 1; + var b = m[2] ? Number(m[2]) : 0; + var indices = Selector.pseudos.getIndices(a, b, nodes.length); + for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { + for (var j = 0; j < l; j++) + if (node.nodeIndex == indices[j]) results.push(node); + } + } + h.unmark(nodes); + h.unmark(indexed); + return results; + }, + + 'empty': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) { + if (node.tagName == '!' || node.firstChild) continue; + results.push(node); + } + return results; + }, + + 'not': function(nodes, selector, root) { + var h = Selector.handlers, selectorType, m; + var exclusions = new Selector(selector).findElements(root); + h.mark(exclusions); + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node._countedByPrototype) results.push(node); + h.unmark(exclusions); + return results; + }, + + 'enabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (!node.disabled && (!node.type || node.type !== 'hidden')) + results.push(node); + return results; + }, + + 'disabled': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.disabled) results.push(node); + return results; + }, + + 'checked': function(nodes, value, root) { + for (var i = 0, results = [], node; node = nodes[i]; i++) + if (node.checked) results.push(node); + return results; + } + }, + + operators: { + '=': function(nv, v) { return nv == v; }, + '!=': function(nv, v) { return nv != v; }, + '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, + '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, + '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, + '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, + '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + + '-').include('-' + (v || "").toUpperCase() + '-'); } + }, + + split: function(expression) { + var expressions = []; + expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { + expressions.push(m[1].strip()); + }); + return expressions; + }, + + matchElements: function(elements, expression) { + var matches = $$(expression), h = Selector.handlers; + h.mark(matches); + for (var i = 0, results = [], element; element = elements[i]; i++) + if (element._countedByPrototype) results.push(element); + h.unmark(matches); + return results; + }, + + findElement: function(elements, expression, index) { + if (Object.isNumber(expression)) { + index = expression; expression = false; + } + return Selector.matchElements(elements, expression || '*')[index || 0]; + }, + + findChildElements: function(element, expressions) { + expressions = Selector.split(expressions.join(',')); + var results = [], h = Selector.handlers; + for (var i = 0, l = expressions.length, selector; i < l; i++) { + selector = new Selector(expressions[i].strip()); + h.concat(results, selector.findElements(element)); + } + return (l > 1) ? h.unique(results) : results; + } +}); + +if (Prototype.Browser.IE) { + Object.extend(Selector.handlers, { + concat: function(a, b) { + for (var i = 0, node; node = b[i]; i++) + if (node.tagName !== "!") a.push(node); + return a; + } + }); +} + +function $$() { + return Selector.findChildElements(document, $A(arguments)); +} + +var Form = { + reset: function(form) { + form = $(form); + form.reset(); + return form; + }, + + serializeElements: function(elements, options) { + if (typeof options != 'object') options = { hash: !!options }; + else if (Object.isUndefined(options.hash)) options.hash = true; + var key, value, submitted = false, submit = options.submit; + + var data = elements.inject({ }, function(result, element) { + if (!element.disabled && element.name) { + key = element.name; value = $(element).getValue(); + if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted && + submit !== false && (!submit || key == submit) && (submitted = true)))) { + if (key in result) { + if (!Object.isArray(result[key])) result[key] = [result[key]]; + result[key].push(value); + } + else result[key] = value; + } + } + return result; + }); + + return options.hash ? data : Object.toQueryString(data); + } +}; + +Form.Methods = { + serialize: function(form, options) { + return Form.serializeElements(Form.getElements(form), options); + }, + + getElements: function(form) { + var elements = $(form).getElementsByTagName('*'), + element, + arr = [ ], + serializers = Form.Element.Serializers; + for (var i = 0; element = elements[i]; i++) { + arr.push(element); + } + return arr.inject([], function(elements, child) { + if (serializers[child.tagName.toLowerCase()]) + elements.push(Element.extend(child)); + return elements; + }) + }, + + getInputs: function(form, typeName, name) { + form = $(form); + var inputs = form.getElementsByTagName('input'); + + if (!typeName && !name) return $A(inputs).map(Element.extend); + + for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) { + var input = inputs[i]; + if ((typeName && input.type != typeName) || (name && input.name != name)) + continue; + matchingInputs.push(Element.extend(input)); + } + + return matchingInputs; + }, + + disable: function(form) { + form = $(form); + Form.getElements(form).invoke('disable'); + return form; + }, + + enable: function(form) { + form = $(form); + Form.getElements(form).invoke('enable'); + return form; + }, + + findFirstElement: function(form) { + var elements = $(form).getElements().findAll(function(element) { + return 'hidden' != element.type && !element.disabled; + }); + var firstByIndex = elements.findAll(function(element) { + return element.hasAttribute('tabIndex') && element.tabIndex >= 0; + }).sortBy(function(element) { return element.tabIndex }).first(); + + return firstByIndex ? firstByIndex : elements.find(function(element) { + return /^(?:input|select|textarea)$/i.test(element.tagName); + }); + }, + + focusFirstElement: function(form) { + form = $(form); + form.findFirstElement().activate(); + return form; + }, + + request: function(form, options) { + form = $(form), options = Object.clone(options || { }); + + var params = options.parameters, action = form.readAttribute('action') || ''; + if (action.blank()) action = window.location.href; + options.parameters = form.serialize(true); + + if (params) { + if (Object.isString(params)) params = params.toQueryParams(); + Object.extend(options.parameters, params); + } + + if (form.hasAttribute('method') && !options.method) + options.method = form.method; + + return new Ajax.Request(action, options); + } +}; + +/*--------------------------------------------------------------------------*/ + + +Form.Element = { + focus: function(element) { + $(element).focus(); + return element; + }, + + select: function(element) { + $(element).select(); + return element; + } +}; + +Form.Element.Methods = { + + serialize: function(element) { + element = $(element); + if (!element.disabled && element.name) { + var value = element.getValue(); + if (value != undefined) { + var pair = { }; + pair[element.name] = value; + return Object.toQueryString(pair); + } + } + return ''; + }, + + getValue: function(element) { + element = $(element); + var method = element.tagName.toLowerCase(); + return Form.Element.Serializers[method](element); + }, + + setValue: function(element, value) { + element = $(element); + var method = element.tagName.toLowerCase(); + Form.Element.Serializers[method](element, value); + return element; + }, + + clear: function(element) { + $(element).value = ''; + return element; + }, + + present: function(element) { + return $(element).value != ''; + }, + + activate: function(element) { + element = $(element); + try { + element.focus(); + if (element.select && (element.tagName.toLowerCase() != 'input' || + !(/^(?:button|reset|submit)$/i.test(element.type)))) + element.select(); + } catch (e) { } + return element; + }, + + disable: function(element) { + element = $(element); + element.disabled = true; + return element; + }, + + enable: function(element) { + element = $(element); + element.disabled = false; + return element; + } +}; + +/*--------------------------------------------------------------------------*/ + +var Field = Form.Element; + +var $F = Form.Element.Methods.getValue; + +/*--------------------------------------------------------------------------*/ + +Form.Element.Serializers = { + input: function(element, value) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + return Form.Element.Serializers.inputSelector(element, value); + default: + return Form.Element.Serializers.textarea(element, value); + } + }, + + inputSelector: function(element, value) { + if (Object.isUndefined(value)) return element.checked ? element.value : null; + else element.checked = !!value; + }, + + textarea: function(element, value) { + if (Object.isUndefined(value)) return element.value; + else element.value = value; + }, + + select: function(element, value) { + if (Object.isUndefined(value)) + return this[element.type == 'select-one' ? + 'selectOne' : 'selectMany'](element); + else { + var opt, currentValue, single = !Object.isArray(value); + for (var i = 0, length = element.length; i < length; i++) { + opt = element.options[i]; + currentValue = this.optionValue(opt); + if (single) { + if (currentValue == value) { + opt.selected = true; + return; + } + } + else opt.selected = value.include(currentValue); + } + } + }, + + selectOne: function(element) { + var index = element.selectedIndex; + return index >= 0 ? this.optionValue(element.options[index]) : null; + }, + + selectMany: function(element) { + var values, length = element.length; + if (!length) return null; + + for (var i = 0, values = []; i < length; i++) { + var opt = element.options[i]; + if (opt.selected) values.push(this.optionValue(opt)); + } + return values; + }, + + optionValue: function(opt) { + return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text; + } +}; + +/*--------------------------------------------------------------------------*/ + + +Abstract.TimedObserver = Class.create(PeriodicalExecuter, { + initialize: function($super, element, frequency, callback) { + $super(callback, frequency); + this.element = $(element); + this.lastValue = this.getValue(); + }, + + execute: function() { + var value = this.getValue(); + if (Object.isString(this.lastValue) && Object.isString(value) ? + this.lastValue != value : String(this.lastValue) != String(value)) { + this.callback(this.element, value); + this.lastValue = value; + } + } +}); + +Form.Element.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.Observer = Class.create(Abstract.TimedObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); + +/*--------------------------------------------------------------------------*/ + +Abstract.EventObserver = Class.create({ + initialize: function(element, callback) { + this.element = $(element); + this.callback = callback; + + this.lastValue = this.getValue(); + if (this.element.tagName.toLowerCase() == 'form') + this.registerFormCallbacks(); + else + this.registerCallback(this.element); + }, + + onElementEvent: function() { + var value = this.getValue(); + if (this.lastValue != value) { + this.callback(this.element, value); + this.lastValue = value; + } + }, + + registerFormCallbacks: function() { + Form.getElements(this.element).each(this.registerCallback, this); + }, + + registerCallback: function(element) { + if (element.type) { + switch (element.type.toLowerCase()) { + case 'checkbox': + case 'radio': + Event.observe(element, 'click', this.onElementEvent.bind(this)); + break; + default: + Event.observe(element, 'change', this.onElementEvent.bind(this)); + break; + } + } + } +}); + +Form.Element.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.Element.getValue(this.element); + } +}); + +Form.EventObserver = Class.create(Abstract.EventObserver, { + getValue: function() { + return Form.serialize(this.element); + } +}); +(function() { + + var Event = { + KEY_BACKSPACE: 8, + KEY_TAB: 9, + KEY_RETURN: 13, + KEY_ESC: 27, + KEY_LEFT: 37, + KEY_UP: 38, + KEY_RIGHT: 39, + KEY_DOWN: 40, + KEY_DELETE: 46, + KEY_HOME: 36, + KEY_END: 35, + KEY_PAGEUP: 33, + KEY_PAGEDOWN: 34, + KEY_INSERT: 45, + + cache: {} + }; + + var docEl = document.documentElement; + var MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED = 'onmouseenter' in docEl + && 'onmouseleave' in docEl; + + var _isButton; + if (Prototype.Browser.IE) { + var buttonMap = { 0: 1, 1: 4, 2: 2 }; + _isButton = function(event, code) { + return event.button === buttonMap[code]; + }; + } else if (Prototype.Browser.WebKit) { + _isButton = function(event, code) { + switch (code) { + case 0: return event.which == 1 && !event.metaKey; + case 1: return event.which == 1 && event.metaKey; + default: return false; + } + }; + } else { + _isButton = function(event, code) { + return event.which ? (event.which === code + 1) : (event.button === code); + }; + } + + function isLeftClick(event) { return _isButton(event, 0) } + + function isMiddleClick(event) { return _isButton(event, 1) } + + function isRightClick(event) { return _isButton(event, 2) } + + function element(event) { + event = Event.extend(event); + + var node = event.target, type = event.type, + currentTarget = event.currentTarget; + + if (currentTarget && currentTarget.tagName) { + if (type === 'load' || type === 'error' || + (type === 'click' && currentTarget.tagName.toLowerCase() === 'input' + && currentTarget.type === 'radio')) + node = currentTarget; + } + + if (node.nodeType == Node.TEXT_NODE) + node = node.parentNode; + + return Element.extend(node); + } + + function findElement(event, expression) { + var element = Event.element(event); + if (!expression) return element; + var elements = [element].concat(element.ancestors()); + return Selector.findElement(elements, expression, 0); + } + + function pointer(event) { + return { x: pointerX(event), y: pointerY(event) }; + } + + function pointerX(event) { + var docElement = document.documentElement, + body = document.body || { scrollLeft: 0 }; + + return event.pageX || (event.clientX + + (docElement.scrollLeft || body.scrollLeft) - + (docElement.clientLeft || 0)); + } + + function pointerY(event) { + var docElement = document.documentElement, + body = document.body || { scrollTop: 0 }; + + return event.pageY || (event.clientY + + (docElement.scrollTop || body.scrollTop) - + (docElement.clientTop || 0)); + } + + + function stop(event) { + Event.extend(event); + event.preventDefault(); + event.stopPropagation(); + + event.stopped = true; + } + + Event.Methods = { + isLeftClick: isLeftClick, + isMiddleClick: isMiddleClick, + isRightClick: isRightClick, + + element: element, + findElement: findElement, + + pointer: pointer, + pointerX: pointerX, + pointerY: pointerY, + + stop: stop + }; + + + var methods = Object.keys(Event.Methods).inject({ }, function(m, name) { + m[name] = Event.Methods[name].methodize(); + return m; + }); + + if (Prototype.Browser.IE) { + function _relatedTarget(event) { + var element; + switch (event.type) { + case 'mouseover': element = event.fromElement; break; + case 'mouseout': element = event.toElement; break; + default: return null; + } + return Element.extend(element); + } + + Object.extend(methods, { + stopPropagation: function() { this.cancelBubble = true }, + preventDefault: function() { this.returnValue = false }, + inspect: function() { return '[object Event]' } + }); + + Event.extend = function(event, element) { + if (!event) return false; + if (event._extendedByPrototype) return event; + + event._extendedByPrototype = Prototype.emptyFunction; + var pointer = Event.pointer(event); + + Object.extend(event, { + target: event.srcElement || element, + relatedTarget: _relatedTarget(event), + pageX: pointer.x, + pageY: pointer.y + }); + + return Object.extend(event, methods); + }; + } else { + Event.prototype = window.Event.prototype || document.createEvent('HTMLEvents').__proto__; + Object.extend(Event.prototype, methods); + Event.extend = Prototype.K; + } + + function _createResponder(element, eventName, handler) { + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) { + CACHE.push(element); + registry = Element.retrieve(element, 'prototype_event_registry', $H()); + } + + var respondersForEvent = registry.get(eventName); + if (Object.isUndefined(respondersForEvent)) { + respondersForEvent = []; + registry.set(eventName, respondersForEvent); + } + + if (respondersForEvent.pluck('handler').include(handler)) return false; + + var responder; + if (eventName.include(":")) { + responder = function(event) { + if (Object.isUndefined(event.eventName)) + return false; + + if (event.eventName !== eventName) + return false; + + Event.extend(event, element); + handler.call(element, event); + }; + } else { + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED && + (eventName === "mouseenter" || eventName === "mouseleave")) { + if (eventName === "mouseenter" || eventName === "mouseleave") { + responder = function(event) { + Event.extend(event, element); + + var parent = event.relatedTarget; + while (parent && parent !== element) { + try { parent = parent.parentNode; } + catch(e) { parent = element; } + } + + if (parent === element) return; + + handler.call(element, event); + }; + } + } else { + responder = function(event) { + Event.extend(event, element); + handler.call(element, event); + }; + } + } + + responder.handler = handler; + respondersForEvent.push(responder); + return responder; + } + + function _destroyCache() { + for (var i = 0, length = CACHE.length; i < length; i++) { + Event.stopObserving(CACHE[i]); + CACHE[i] = null; + } + } + + var CACHE = []; + + if (Prototype.Browser.IE) + window.attachEvent('onunload', _destroyCache); + + if (Prototype.Browser.WebKit) + window.addEventListener('unload', Prototype.emptyFunction, false); + + + var _getDOMEventName = Prototype.K; + + if (!MOUSEENTER_MOUSELEAVE_EVENTS_SUPPORTED) { + _getDOMEventName = function(eventName) { + var translations = { mouseenter: "mouseover", mouseleave: "mouseout" }; + return eventName in translations ? translations[eventName] : eventName; + }; + } + + function observe(element, eventName, handler) { + element = $(element); + + var responder = _createResponder(element, eventName, handler); + + if (!responder) return element; + + if (eventName.include(':')) { + if (element.addEventListener) + element.addEventListener("dataavailable", responder, false); + else { + element.attachEvent("ondataavailable", responder); + element.attachEvent("onfilterchange", responder); + } + } else { + var actualEventName = _getDOMEventName(eventName); + + if (element.addEventListener) + element.addEventListener(actualEventName, responder, false); + else + element.attachEvent("on" + actualEventName, responder); + } + + return element; + } + + function stopObserving(element, eventName, handler) { + element = $(element); + + var registry = Element.retrieve(element, 'prototype_event_registry'); + + if (Object.isUndefined(registry)) return element; + + if (eventName && !handler) { + var responders = registry.get(eventName); + + if (Object.isUndefined(responders)) return element; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + return element; + } else if (!eventName) { + registry.each( function(pair) { + var eventName = pair.key, responders = pair.value; + + responders.each( function(r) { + Element.stopObserving(element, eventName, r.handler); + }); + }); + return element; + } + + var responders = registry.get(eventName); + + if (!responders) return; + + var responder = responders.find( function(r) { return r.handler === handler; }); + if (!responder) return element; + + var actualEventName = _getDOMEventName(eventName); + + if (eventName.include(':')) { + if (element.removeEventListener) + element.removeEventListener("dataavailable", responder, false); + else { + element.detachEvent("ondataavailable", responder); + element.detachEvent("onfilterchange", responder); + } + } else { + if (element.removeEventListener) + element.removeEventListener(actualEventName, responder, false); + else + element.detachEvent('on' + actualEventName, responder); + } + + registry.set(eventName, responders.without(responder)); + + return element; + } + + function fire(element, eventName, memo, bubble) { + element = $(element); + + if (Object.isUndefined(bubble)) + bubble = true; + + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent('HTMLEvents'); + event.initEvent('dataavailable', true, true); + } else { + event = document.createEventObject(); + event.eventType = bubble ? 'ondataavailable' : 'onfilterchange'; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) + element.dispatchEvent(event); + else + element.fireEvent(event.eventType, event); + + return Event.extend(event); + } + + + Object.extend(Event, Event.Methods); + + Object.extend(Event, { + fire: fire, + observe: observe, + stopObserving: stopObserving + }); + + Element.addMethods({ + fire: fire, + + observe: observe, + + stopObserving: stopObserving + }); + + Object.extend(document, { + fire: fire.methodize(), + + observe: observe.methodize(), + + stopObserving: stopObserving.methodize(), + + loaded: false + }); + + if (window.Event) Object.extend(window.Event, Event); + else window.Event = Event; +})(); + +(function() { + /* Support for the DOMContentLoaded event is based on work by Dan Webb, + Matthias Miller, Dean Edwards, John Resig, and Diego Perini. */ + + var timer; + + function fireContentLoadedEvent() { + if (document.loaded) return; + if (timer) window.clearTimeout(timer); + document.loaded = true; + document.fire('dom:loaded'); + } + + function checkReadyState() { + if (document.readyState === 'complete') { + document.stopObserving('readystatechange', checkReadyState); + fireContentLoadedEvent(); + } + } + + function pollDoScroll() { + try { document.documentElement.doScroll('left'); } + catch(e) { + timer = pollDoScroll.defer(); + return; + } + fireContentLoadedEvent(); + } + + if (document.addEventListener) { + document.addEventListener('DOMContentLoaded', fireContentLoadedEvent, false); + } else { + document.observe('readystatechange', checkReadyState); + if (window == top) + timer = pollDoScroll.defer(); + } + + Event.observe(window, 'load', fireContentLoadedEvent); +})(); + +Element.addMethods(); + +/*------------------------------- DEPRECATED -------------------------------*/ + +Hash.toQueryString = Object.toQueryString; + +var Toggle = { display: Element.toggle }; + +Element.Methods.childOf = Element.Methods.descendantOf; + +var Insertion = { + Before: function(element, content) { + return Element.insert(element, {before:content}); + }, + + Top: function(element, content) { + return Element.insert(element, {top:content}); + }, + + Bottom: function(element, content) { + return Element.insert(element, {bottom:content}); + }, + + After: function(element, content) { + return Element.insert(element, {after:content}); + } +}; + +var $continue = new Error('"throw $continue" is deprecated, use "return" instead'); + +var Position = { + includeScrollOffsets: false, + + prepare: function() { + this.deltaX = window.pageXOffset + || document.documentElement.scrollLeft + || document.body.scrollLeft + || 0; + this.deltaY = window.pageYOffset + || document.documentElement.scrollTop + || document.body.scrollTop + || 0; + }, + + within: function(element, x, y) { + if (this.includeScrollOffsets) + return this.withinIncludingScrolloffsets(element, x, y); + this.xcomp = x; + this.ycomp = y; + this.offset = Element.cumulativeOffset(element); + + return (y >= this.offset[1] && + y < this.offset[1] + element.offsetHeight && + x >= this.offset[0] && + x < this.offset[0] + element.offsetWidth); + }, + + withinIncludingScrolloffsets: function(element, x, y) { + var offsetcache = Element.cumulativeScrollOffset(element); + + this.xcomp = x + offsetcache[0] - this.deltaX; + this.ycomp = y + offsetcache[1] - this.deltaY; + this.offset = Element.cumulativeOffset(element); + + return (this.ycomp >= this.offset[1] && + this.ycomp < this.offset[1] + element.offsetHeight && + this.xcomp >= this.offset[0] && + this.xcomp < this.offset[0] + element.offsetWidth); + }, + + overlap: function(mode, element) { + if (!mode) return 0; + if (mode == 'vertical') + return ((this.offset[1] + element.offsetHeight) - this.ycomp) / + element.offsetHeight; + if (mode == 'horizontal') + return ((this.offset[0] + element.offsetWidth) - this.xcomp) / + element.offsetWidth; + }, + + + cumulativeOffset: Element.Methods.cumulativeOffset, + + positionedOffset: Element.Methods.positionedOffset, + + absolutize: function(element) { + Position.prepare(); + return Element.absolutize(element); + }, + + relativize: function(element) { + Position.prepare(); + return Element.relativize(element); + }, + + realOffset: Element.Methods.cumulativeScrollOffset, + + offsetParent: Element.Methods.getOffsetParent, + + page: Element.Methods.viewportOffset, + + clone: function(source, target, options) { + options = options || { }; + return Element.clonePosition(target, source, options); + } +}; + +/*--------------------------------------------------------------------------*/ + +if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){ + function iter(name) { + return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]"; + } + + instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ? + function(element, className) { + className = className.toString().strip(); + var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className); + return cond ? document._getElementsByXPath('.//*' + cond, element) : []; + } : function(element, className) { + className = className.toString().strip(); + var elements = [], classNames = (/\s/.test(className) ? $w(className) : null); + if (!classNames && !className) return elements; + + var nodes = $(element).getElementsByTagName('*'); + className = ' ' + className + ' '; + + for (var i = 0, child, cn; child = nodes[i]; i++) { + if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) || + (classNames && classNames.all(function(name) { + return !name.toString().blank() && cn.include(' ' + name + ' '); + })))) + elements.push(Element.extend(child)); + } + return elements; + }; + + return function(className, parentElement) { + return $(parentElement || document.body).getElementsByClassName(className); + }; +}(Element.Methods); + +/*--------------------------------------------------------------------------*/ + +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(' '); + } +}; + +Object.extend(Element.ClassNames.prototype, Enumerable); + +/*--------------------------------------------------------------------------*/ diff --git a/doc/javascripts/tabs.js b/doc/javascripts/tabs.js new file mode 100644 index 000000000..7c974209f --- /dev/null +++ b/doc/javascripts/tabs.js @@ -0,0 +1,506 @@ +/** + * @author Ryan Johnson + * @copyright 2008 PersonalGrid Corporation + * @package LivePipe UI + * @license MIT + * @url http://livepipe.net/core + * @require prototype.js + */ + +if(typeof(Control) == 'undefined') + Control = {}; + +var $proc = function(proc){ + return typeof(proc) == 'function' ? proc : function(){return proc}; +}; + +var $value = function(value){ + return typeof(value) == 'function' ? value() : value; +}; + +Object.Event = { + extend: function(object){ + object._objectEventSetup = function(event_name){ + this._observers = this._observers || {}; + this._observers[event_name] = this._observers[event_name] || []; + }; + object.observe = function(event_name,observer){ + if(typeof(event_name) == 'string' && typeof(observer) != 'undefined'){ + this._objectEventSetup(event_name); + if(!this._observers[event_name].include(observer)) + this._observers[event_name].push(observer); + }else + for(var e in event_name) + this.observe(e,event_name[e]); + }; + object.stopObserving = function(event_name,observer){ + this._objectEventSetup(event_name); + if(event_name && observer) + this._observers[event_name] = this._observers[event_name].without(observer); + else if(event_name) + this._observers[event_name] = []; + else + this._observers = {}; + }; + object.observeOnce = function(event_name,outer_observer){ + var inner_observer = function(){ + outer_observer.apply(this,arguments); + this.stopObserving(event_name,inner_observer); + }.bind(this); + this._objectEventSetup(event_name); + this._observers[event_name].push(inner_observer); + }; + object.notify = function(event_name){ + this._objectEventSetup(event_name); + var collected_return_values = []; + var args = $A(arguments).slice(1); + try{ + for(var i = 0; i < this._observers[event_name].length; ++i) + collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null); + }catch(e){ + if(e == $break) + return false; + else + throw e; + } + return collected_return_values; + }; + if(object.prototype){ + object.prototype._objectEventSetup = object._objectEventSetup; + object.prototype.observe = object.observe; + object.prototype.stopObserving = object.stopObserving; + object.prototype.observeOnce = object.observeOnce; + object.prototype.notify = function(event_name){ + if(object.notify){ + var args = $A(arguments).slice(1); + args.unshift(this); + args.unshift(event_name); + object.notify.apply(object,args); + } + this._objectEventSetup(event_name); + var args = $A(arguments).slice(1); + var collected_return_values = []; + try{ + if(this.options && this.options[event_name] && typeof(this.options[event_name]) == 'function') + collected_return_values.push(this.options[event_name].apply(this,args) || null); + for(var i = 0; i < this._observers[event_name].length; ++i) + collected_return_values.push(this._observers[event_name][i].apply(this._observers[event_name][i],args) || null); + }catch(e){ + if(e == $break) + return false; + else + throw e; + } + return collected_return_values; + }; + } + } +}; + +/* Begin Core Extensions */ + +//Element.observeOnce +Element.addMethods({ + observeOnce: function(element,event_name,outer_callback){ + var inner_callback = function(){ + outer_callback.apply(this,arguments); + Element.stopObserving(element,event_name,inner_callback); + }; + Element.observe(element,event_name,inner_callback); + } +}); + +//mouseenter, mouseleave +//from http://dev.rubyonrails.org/attachment/ticket/8354/event_mouseenter_106rc1.patch +Object.extend(Event, (function() { + var cache = Event.cache; + + function getEventID(element) { + if (element._prototypeEventID) return element._prototypeEventID[0]; + arguments.callee.id = arguments.callee.id || 1; + return element._prototypeEventID = [++arguments.callee.id]; + } + + function getDOMEventName(eventName) { + if (eventName && eventName.include(':')) return "dataavailable"; + //begin extension + if(!Prototype.Browser.IE){ + eventName = { + mouseenter: 'mouseover', + mouseleave: 'mouseout' + }[eventName] || eventName; + } + //end extension + return eventName; + } + + function getCacheForID(id) { + return cache[id] = cache[id] || { }; + } + + function getWrappersForEventName(id, eventName) { + var c = getCacheForID(id); + return c[eventName] = c[eventName] || []; + } + + function createWrapper(element, eventName, handler) { + var id = getEventID(element); + var c = getWrappersForEventName(id, eventName); + if (c.pluck("handler").include(handler)) return false; + + var wrapper = function(event) { + if (!Event || !Event.extend || + (event.eventName && event.eventName != eventName)) + return false; + + Event.extend(event); + handler.call(element, event); + }; + + //begin extension + if(!(Prototype.Browser.IE) && ['mouseenter','mouseleave'].include(eventName)){ + wrapper = wrapper.wrap(function(proceed,event) { + var rel = event.relatedTarget; + var cur = event.currentTarget; + if(rel && rel.nodeType == Node.TEXT_NODE) + rel = rel.parentNode; + if(rel && rel != cur && !rel.descendantOf(cur)) + return proceed(event); + }); + } + //end extension + + wrapper.handler = handler; + c.push(wrapper); + return wrapper; + } + + function findWrapper(id, eventName, handler) { + var c = getWrappersForEventName(id, eventName); + return c.find(function(wrapper) { return wrapper.handler == handler }); + } + + function destroyWrapper(id, eventName, handler) { + var c = getCacheForID(id); + if (!c[eventName]) return false; + c[eventName] = c[eventName].without(findWrapper(id, eventName, handler)); + } + + function destroyCache() { + for (var id in cache) + for (var eventName in cache[id]) + cache[id][eventName] = null; + } + + if (window.attachEvent) { + window.attachEvent("onunload", destroyCache); + } + + return { + observe: function(element, eventName, handler) { + element = $(element); + var name = getDOMEventName(eventName); + + var wrapper = createWrapper(element, eventName, handler); + if (!wrapper) return element; + + if (element.addEventListener) { + element.addEventListener(name, wrapper, false); + } else { + element.attachEvent("on" + name, wrapper); + } + + return element; + }, + + stopObserving: function(element, eventName, handler) { + element = $(element); + var id = getEventID(element), name = getDOMEventName(eventName); + + if (!handler && eventName) { + getWrappersForEventName(id, eventName).each(function(wrapper) { + element.stopObserving(eventName, wrapper.handler); + }); + return element; + + } else if (!eventName) { + Object.keys(getCacheForID(id)).each(function(eventName) { + element.stopObserving(eventName); + }); + return element; + } + + var wrapper = findWrapper(id, eventName, handler); + if (!wrapper) return element; + + if (element.removeEventListener) { + element.removeEventListener(name, wrapper, false); + } else { + element.detachEvent("on" + name, wrapper); + } + + destroyWrapper(id, eventName, handler); + + return element; + }, + + fire: function(element, eventName, memo) { + element = $(element); + if (element == document && document.createEvent && !element.dispatchEvent) + element = document.documentElement; + + var event; + if (document.createEvent) { + event = document.createEvent("HTMLEvents"); + event.initEvent("dataavailable", true, true); + } else { + event = document.createEventObject(); + event.eventType = "ondataavailable"; + } + + event.eventName = eventName; + event.memo = memo || { }; + + if (document.createEvent) { + element.dispatchEvent(event); + } else { + element.fireEvent(event.eventType, event); + } + + return Event.extend(event); + } + }; +})()); + +Object.extend(Event, Event.Methods); + +Element.addMethods({ + fire: Event.fire, + observe: Event.observe, + stopObserving: Event.stopObserving +}); + +Object.extend(document, { + fire: Element.Methods.fire.methodize(), + observe: Element.Methods.observe.methodize(), + stopObserving: Element.Methods.stopObserving.methodize() +}); + +//mouse:wheel +(function(){ + function wheel(event){ + var delta; + // normalize the delta + if(event.wheelDelta) // IE & Opera + delta = event.wheelDelta / 120; + else if (event.detail) // W3C + delta =- event.detail / 3; + if(!delta) + return; + var custom_event = Event.element(event).fire('mouse:wheel',{ + delta: delta + }); + if(custom_event.stopped){ + Event.stop(event); + return false; + } + } + document.observe('mousewheel',wheel); + document.observe('DOMMouseScroll',wheel); +})(); + +/* End Core Extensions */ + +//from PrototypeUI +var IframeShim = Class.create({ + initialize: function() { + this.element = new Element('iframe',{ + style: 'position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);display:none', + src: 'javascript:void(0);', + frameborder: 0 + }); + $(document.body).insert(this.element); + }, + hide: function() { + this.element.hide(); + return this; + }, + show: function() { + this.element.show(); + return this; + }, + positionUnder: function(element) { + var element = $(element); + var offset = element.cumulativeOffset(); + var dimensions = element.getDimensions(); + this.element.setStyle({ + left: offset[0] + 'px', + top: offset[1] + 'px', + width: dimensions.width + 'px', + height: dimensions.height + 'px', + zIndex: element.getStyle('zIndex') - 1 + }).show(); + return this; + }, + setBounds: function(bounds) { + for(prop in bounds) + bounds[prop] += 'px'; + this.element.setStyle(bounds); + return this; + }, + destroy: function() { + if(this.element) + this.element.remove(); + return this; + } +}); + +/** + * @author Ryan Johnson + * @copyright 2008 PersonalGrid Corporation + * @package LivePipe UI + * @license MIT + * @url http://livepipe.net/control/tabs + * @require prototype.js, livepipe.js + */ + +/*global window, document, Prototype, $, $A, $H, $break, Class, Element, Event, Control */ + +if(typeof(Prototype) == "undefined") { + throw "Control.Tabs requires Prototype to be loaded."; } +if(typeof(Object.Event) == "undefined") { + throw "Control.Tabs requires Object.Event to be loaded."; } + +Control.Tabs = Class.create({ + initialize: function(tab_list_container,options){ + if(!$(tab_list_container)) { + throw "Control.Tabs could not find the element: " + tab_list_container; } + this.activeContainer = false; + this.activeLink = false; + this.containers = $H({}); + this.links = []; + Control.Tabs.instances.push(this); + this.options = { + beforeChange: Prototype.emptyFunction, + afterChange: Prototype.emptyFunction, + hover: false, + linkSelector: 'li a', + setClassOnContainer: false, + activeClassName: 'active', + defaultTab: 'first', + autoLinkExternal: true, + targetRegExp: /#(.+)$/, + showFunction: Element.show, + hideFunction: Element.hide + }; + Object.extend(this.options,options || {}); + (typeof(this.options.linkSelector == 'string') ? + $(tab_list_container).select(this.options.linkSelector) : + this.options.linkSelector($(tab_list_container)) + ).findAll(function(link){ + return (/^#/).exec((Prototype.Browser.WebKit ? decodeURIComponent(link.href) : link.href).replace(window.location.href.split('#')[0],'')); + }).each(function(link){ + this.addTab(link); + }.bind(this)); + this.containers.values().each(Element.hide); + if(this.options.defaultTab == 'first') { + this.setActiveTab(this.links.first()); + } else if(this.options.defaultTab == 'last') { + this.setActiveTab(this.links.last()); + } else { + this.setActiveTab(this.options.defaultTab); } + var targets = this.options.targetRegExp.exec(window.location); + if(targets && targets[1]){ + targets[1].split(',').each(function(target){ + this.setActiveTab(this.links.find(function(link){ + return link.key == target; + })); + }.bind(this)); + } + if(this.options.autoLinkExternal){ + $A(document.getElementsByTagName('a')).each(function(a){ + if(!this.links.include(a)){ + var clean_href = a.href.replace(window.location.href.split('#')[0],''); + if(clean_href.substring(0,1) == '#'){ + if(this.containers.keys().include(clean_href.substring(1))){ + $(a).observe('click',function(event,clean_href){ + this.setActiveTab(clean_href.substring(1)); + }.bindAsEventListener(this,clean_href)); + } + } + } + }.bind(this)); + } + }, + addTab: function(link){ + this.links.push(link); + link.key = link.getAttribute('href').replace(window.location.href.split('#')[0],'').split('#').last().replace(/#/,''); + var container = $(link.key); + if(!container) { + throw "Control.Tabs: #" + link.key + " was not found on the page."; } + this.containers.set(link.key,container); + link[this.options.hover ? 'onmouseover' : 'onclick'] = function(link){ + if(window.event) { + Event.stop(window.event); } + this.setActiveTab(link); + return false; + }.bind(this,link); + }, + setActiveTab: function(link){ + if(!link && typeof(link) == 'undefined') { + return; } + if(typeof(link) == 'string'){ + this.setActiveTab(this.links.find(function(_link){ + return _link.key == link; + })); + }else if(typeof(link) == 'number'){ + this.setActiveTab(this.links[link]); + }else{ + if(this.notify('beforeChange',this.activeContainer,this.containers.get(link.key)) === false) { + return; } + if(this.activeContainer) { + this.options.hideFunction(this.activeContainer); } + this.links.each(function(item){ + (this.options.setClassOnContainer ? $(item.parentNode) : item).removeClassName(this.options.activeClassName); + }.bind(this)); + (this.options.setClassOnContainer ? $(link.parentNode) : link).addClassName(this.options.activeClassName); + this.activeContainer = this.containers.get(link.key); + this.activeLink = link; + this.options.showFunction(this.containers.get(link.key)); + this.notify('afterChange',this.containers.get(link.key)); + } + }, + next: function(){ + this.links.each(function(link,i){ + if(this.activeLink == link && this.links[i + 1]){ + this.setActiveTab(this.links[i + 1]); + throw $break; + } + }.bind(this)); + }, + previous: function(){ + this.links.each(function(link,i){ + if(this.activeLink == link && this.links[i - 1]){ + this.setActiveTab(this.links[i - 1]); + throw $break; + } + }.bind(this)); + }, + first: function(){ + this.setActiveTab(this.links.first()); + }, + last: function(){ + this.setActiveTab(this.links.last()); + } +}); +Object.extend(Control.Tabs,{ + instances: [], + findByTabId: function(id){ + return Control.Tabs.instances.find(function(tab){ + return tab.links.find(function(link){ + return link.key == id; + }); + }); + } +}); +Object.Event.extend(Control.Tabs); diff --git a/doc/language/array/from/index.html b/doc/language/array/from/index.html new file mode 100644 index 000000000..7adcf7a96 --- /dev/null +++ b/doc/language/array/from/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array.from + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Array.from +

    + + + + +
    +
    +
    +
    +
    +
    Array.from(iterable) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/index.html b/doc/language/array/index.html new file mode 100644 index 000000000..19db7fda2 --- /dev/null +++ b/doc/language/array/index.html @@ -0,0 +1,291 @@ + + + + + Prototype v1.7_rc1 API documentation | Array + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Array +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Prototype extends all native JavaScript arrays with quite a few powerful +methods.

    + +

    This is done in two ways:

    + +
      +
    • It mixes in the Enumerable module, which brings in a ton of methods.
    • +
    • It adds quite a few extra methods, which are documented in this section.
    • +
    + +

    With Prototype, arrays become much, much more than the trivial objects we +used to manipulate, limiting ourselves to using their length property and +their [] indexing operator. They become very powerful objects that +greatly simplify the code for 99% of the common use cases involving them.

    + +
    Why you should stop using for...in to iterate
    + +

    Many JavaScript authors have been misled into using the for...in JavaScript +construct to loop over array elements. This kind of code just won't work +with Prototype.

    + +

    The ECMA 262 standard, which defines ECMAScript 3rd edition, supposedly +implemented by all major browsers including MSIE, defines ten methods +on Array (§15.4.4), including nice methods like concat, join, +pop, and push.

    + +

    This same standard explicitly defines that the for...in construct (§12.6.4) +exists to enumerate the properties of the object appearing on the right side +of the in keyword. Only properties specifically marked as non-enumerable +are ignored by such a loop. By default, the prototype and length +properties are so marked, which prevents you from enumerating over array +methods when using for...in. This comfort led developers to use for...in as a +shortcut for indexing loops, when it is not its actual purpose.

    + +

    However, Prototype has no way to mark the methods it adds to +Array.prototype as non-enumerable. Therefore, using for...in on arrays +when using Prototype will enumerate all extended methods as well, such as +those coming from the Enumerable module, and those Prototype puts in the +Array namespace (listed further below).

    + +
    What you should use instead
    + +

    You can revert to vanilla loops:

    + +
    for (var index = 0; index < myArray.length; ++index) {
    +  var item = myArray[index];
    +  // Your code working on item here...
    +}
    +
    +
    + +

    Or you can use iterators, such as Array#each:

    + +
    myArray.each(function(item) {
    +  // Your code working on item here...
    +});
    +
    +
    + +

    The inability to use for...in on arrays is not much of a burden: as you'll +see, most of what you used to loop over arrays for can be concisely done +using the new methods provided by Array or the mixed-in Enumerable +module. So manual loops should be fairly rare.

    + +
    A note on performance
    + +

    Should you have a very large array, using iterators with lexical closures +(anonymous functions that you pass to the iterators and that get invoked at +every loop iteration) in methods like Array#each — _or_ relying on +repetitive array construction (such as uniq), may yield unsatisfactory +performance. In such cases, you're better off writing manual indexing loops, +but take care then to cache the length property and use the prefix ++ +operator:

    + +
    // Custom loop with cached length property: maximum full-loop
    +// performance on very large arrays!
    +for (var index = 0, len = myArray.length; index < len; ++index) {
    +  var item = myArray[index];
    +  // Your code working on item here...
    +}
    +
    +
    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/array/prototype/clear/index.html b/doc/language/array/prototype/clear/index.html new file mode 100644 index 000000000..844740fd2 --- /dev/null +++ b/doc/language/array/prototype/clear/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#clear + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#clear +

    + + + + +
    +
    +
    +
    +
    +
    Array#clear() → Array
    + + +

    Clears the array (makes it empty) and returns the array reference.

    + +
    Example
    + +
    var guys = ['Sam', 'Justin', 'Andrew', 'Dan'];
    +guys.clear();
    +// -> []
    +guys
    +// -> []
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/clone/index.html b/doc/language/array/prototype/clone/index.html new file mode 100644 index 000000000..0870a4d0b --- /dev/null +++ b/doc/language/array/prototype/clone/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#clone +

    + + + + +
    +
    +
    +
    +
    +
    Array#clone() → Array
    + + +

    Returns a duplicate of the array, leaving the original array intact.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/compact/index.html b/doc/language/array/prototype/compact/index.html new file mode 100644 index 000000000..78a0f23ae --- /dev/null +++ b/doc/language/array/prototype/compact/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#compact + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#compact +

    + + + + +
    +
    +
    +
    +
    +
    Array#compact() → Array
    + + +

    Returns a copy of the array without any null or undefined values.

    + +
    Example
    + +
    var orig = [undefined, 'A', undefined, 'B', null, 'C'];
    +var copy = orig.compact();
    +// orig -> [undefined, 'A', undefined, 'B', null, 'C'];
    +// copy -> ['A', 'B', 'C'];
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/first/index.html b/doc/language/array/prototype/first/index.html new file mode 100644 index 000000000..c79c52806 --- /dev/null +++ b/doc/language/array/prototype/first/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#first + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#first +

    + + + + +
    +
    +
    +
    +
    +
    Array#first() → ?
    + + +

    Returns the array's first item (e.g., array[0]).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/flatten/index.html b/doc/language/array/prototype/flatten/index.html new file mode 100644 index 000000000..451a52b31 --- /dev/null +++ b/doc/language/array/prototype/flatten/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#flatten + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#flatten +

    + + + + +
    +
    +
    +
    +
    +
    Array#flatten() → Array
    + + +

    Returns a flattened (one-dimensional) copy of the array, leaving +the original array unchanged.

    + +

    Nested arrays are recursively injected inline. This can prove very +useful when handling the results of a recursive collection algorithm, +for instance.

    + +
    Example
    + +
    var a = ['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]];
    +var b = a.flatten();
    +// a -> ['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]]
    +// b -> ['frank', 'bob', 'lisa', 'jill', 'tom', 'sally']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/indexof/index.html b/doc/language/array/prototype/indexof/index.html new file mode 100644 index 000000000..dcf1aa736 --- /dev/null +++ b/doc/language/array/prototype/indexof/index.html @@ -0,0 +1,180 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#indexOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#indexOf +

    + + + + +
    +
    +
    +
    +
    +
    Array#indexOf(item[, offset = 0]) → Number
    +
      +
    • + item + (?) + – A value that may or may not be in the array. +
    • +
    • + offset + (Number) + – The number of initial items to skip before beginning the search. +
    • +
    + + +

    Returns the index of the first occurrence of item within the array, +or -1 if item doesn't exist in the array. Array#indexOf compares +items using strict equality (===).

    + +
    Examples
    + +
    [3, 5, 6, 1, 20].indexOf(1)
    +// -> 3
    + [3, 5, 6, 1, 20].indexOf(90)
    +// -> -1 (not found)
    + ['1', '2', '3'].indexOf(1);
    +// -> -1 (not found, 1 !== '1')
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/inspect/index.html b/doc/language/array/prototype/inspect/index.html new file mode 100644 index 000000000..e43adb33c --- /dev/null +++ b/doc/language/array/prototype/inspect/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Array#inspect() → String
    + + +

    Returns the debug-oriented string representation of an array.

    + +
    Example
    + +
    ['Apples', {good: 'yes', bad: 'no'}, 3, 34].inspect()
    +// -> "['Apples', [object Object], 3, 34]"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/intersect/index.html b/doc/language/array/prototype/intersect/index.html new file mode 100644 index 000000000..2e0a8383d --- /dev/null +++ b/doc/language/array/prototype/intersect/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#intersect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#intersect +

    + + + + +
    +
    +
    +
    +
    +
    Array#intersect(array) → Array
    +
      +
    • + array + (Array) + – A collection of values. +
    • +
    + + +

    Returns an array containing every item that is shared between the two +given arrays.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/last/index.html b/doc/language/array/prototype/last/index.html new file mode 100644 index 000000000..5ef6c9a8c --- /dev/null +++ b/doc/language/array/prototype/last/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#last + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#last +

    + + + + +
    +
    +
    +
    +
    +
    Array#last() → ?
    + + +

    Returns the array's last item (e.g., array[array.length - 1]).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/lastindexof/index.html b/doc/language/array/prototype/lastindexof/index.html new file mode 100644 index 000000000..5c916e389 --- /dev/null +++ b/doc/language/array/prototype/lastindexof/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#lastIndexOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#lastIndexOf +

    + + + + +
    +
    +
    +
    +
    +
    Array#lastIndexOf(item[, offset]) → Number
    +
      +
    • + item + (?) + – A value that may or may not be in the array. +
    • +
    • + offset + (Number) + – The number of items at the end to skip before beginning the search. +
    • +
    + + +

    Returns the position of the last occurrence of item within the array — or +-1 if item doesn't exist in the array.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/reverse/index.html b/doc/language/array/prototype/reverse/index.html new file mode 100644 index 000000000..a2c4efa20 --- /dev/null +++ b/doc/language/array/prototype/reverse/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#reverse + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#reverse +

    + + + + +
    +
    +
    +
    +
    +
    Array#reverse([inline = true]) → Array
    +
      +
    • + inline + (Boolean) + – Whether to modify the array in place. Defaults to true. Clones the original array when false. +
    • +
    + + +

    Reverses the array's contents, optionally cloning it first.

    + +
    Examples
    + +
    // Making a copy
    +var nums = [3, 5, 6, 1, 20];
    +var rev = nums.reverse(false);
    +// nums -> [3, 5, 6, 1, 20]
    +// rev -> [20, 1, 6, 5, 3]
    + // Working inline
    +var nums = [3, 5, 6, 1, 20];
    +nums.reverse();
    +// nums -> [20, 1, 6, 5, 3]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/size/index.html b/doc/language/array/prototype/size/index.html new file mode 100644 index 000000000..21f717608 --- /dev/null +++ b/doc/language/array/prototype/size/index.html @@ -0,0 +1,158 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#size + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#size +

    + + + + +
    +
    +
    +
    +
    +
    Array#size() → Number
    + + +

    Returns the size of the array (e.g., array.length).

    + +

    This is just a local optimization of the mixed-in Enumerable#size +which avoids array cloning and uses the array's native length property.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/toarray/index.html b/doc/language/array/prototype/toarray/index.html new file mode 100644 index 000000000..1906b689a --- /dev/null +++ b/doc/language/array/prototype/toarray/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#toArray +

    + + + + +
    +
    +
    +
    +
    +
    Array#toArray() → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/uniq/index.html b/doc/language/array/prototype/uniq/index.html new file mode 100644 index 000000000..56733cc6d --- /dev/null +++ b/doc/language/array/prototype/uniq/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#uniq + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#uniq +

    + + + + +
    +
    +
    +
    +
    +
    Array#uniq([sorted = false]) → Array
    +
      +
    • + sorted + (Boolean) + – Whether the array has already been sorted. If true, a less-costly algorithm will be used. +
    • +
    + + +

    Produces a duplicate-free version of an array. If no duplicates are +found, the original array is returned.

    + +

    On large arrays when sorted is false, this method has a potentially +large performance cost.

    + +
    Examples
    + +
    [1, 3, 2, 1].uniq();
    +// -> [1, 2, 3]
    + ['A', 'a'].uniq();
    +// -> ['A', 'a'] (because String comparison is case-sensitive)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/array/prototype/without/index.html b/doc/language/array/prototype/without/index.html new file mode 100644 index 000000000..b97618691 --- /dev/null +++ b/doc/language/array/prototype/without/index.html @@ -0,0 +1,172 @@ + + + + + Prototype v1.7_rc1 API documentation | Array#without + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Array#without +

    + + + + +
    +
    +
    +
    +
    +
    Array#without(value[, value...]) → Array
    +
      +
    • + value + (?) + – A value to exclude. +
    • +
    + + +

    Produces a new version of the array that does not contain any of the +specified values, leaving the original array unchanged.

    + +
    Examples
    + +
    [3, 5, 6].without(3)
    +// -> [5, 6]
    + [3, 5, 6, 20].without(20, 6)
    +// -> [3, 5]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/class/create/index.html b/doc/language/class/create/index.html new file mode 100644 index 000000000..443ba9a47 --- /dev/null +++ b/doc/language/class/create/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Class.create + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Class.create +

    + + + + +
    +
    +
    +
    +
    +
    Class.create([superclass][, methods...]) → Class
    +
      +
    • + superclass + (Class) + – The optional superclass to inherit methods from. +
    • +
    • + methods + (Object) + – An object whose properties will be "mixed-in" to the new class. Any number of mixins can be added; later mixins take precedence. +
    • +
    + + +

    Class.create creates a class and returns a constructor function for +instances of the class. Calling the constructor function (typically as +part of a new statement) will invoke the class's initialize method.

    + +

    Class.create accepts two kinds of arguments. If the first argument is +a Class, it's used as the new class's superclass, and all its methods +are inherited. Otherwise, any arguments passed are treated as objects, +and their methods are copied over ("mixed in") as instance methods of the +new class. In cases of method name overlap, later arguments take +precedence over earlier arguments.

    + +

    If a subclass overrides an instance method declared in a superclass, the +subclass's method can still access the original method. To do so, declare +the subclass's method as normal, but insert $super as the first +argument. This makes $super available as a method for use within the +function.

    + +

    To extend a class after it has been defined, use Class#addMethods.

    + +

    For details, see the +inheritance tutorial +on the Prototype website.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/class/index.html b/doc/language/class/index.html new file mode 100644 index 000000000..0eabe297c --- /dev/null +++ b/doc/language/class/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | Class + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Class +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Manages Prototype's class-based OOP system.

    + +

    Refer to Prototype's web site for a tutorial on classes and +inheritance.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/class/prototype/addmethods/index.html b/doc/language/class/prototype/addmethods/index.html new file mode 100644 index 000000000..9be98c43e --- /dev/null +++ b/doc/language/class/prototype/addmethods/index.html @@ -0,0 +1,201 @@ + + + + + Prototype v1.7_rc1 API documentation | Class#addMethods + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Class#addMethods +

    + + + + +
    +
    +
    +
    +
    +
    Class#addMethods(methods) → Class
    +
      +
    • + methods + (Object) + – The methods to add to the class. +
    • +
    + + +

    Adds methods to an existing class.

    + +

    Class#addMethods is a method available on classes that have been +defined with Class.create. It can be used to add new instance methods +to that class, or overwrite existing methods, after the class has been +defined.

    + +

    New methods propagate down the inheritance chain. If the class has +subclasses, those subclasses will receive the new methods — even in +the context of $super calls. The new methods also propagate to instances +of the class and of all its subclasses, even those that have already been +instantiated.

    + +
    Examples
    + +
    var Animal = Class.create({
    +  initialize: function(name, sound) {
    +    this.name  = name;
    +    this.sound = sound;
    +  },
    +   speak: function() {
    +    alert(this.name + " says: " + this.sound + "!");
    +  }
    +});
    + // subclassing Animal
    +var Snake = Class.create(Animal, {
    +  initialize: function($super, name) {
    +    $super(name, 'hissssssssss');
    +  }
    +});
    + var ringneck = new Snake("Ringneck");
    +ringneck.speak();
    + //-> alerts "Ringneck says: hissssssss!"
    + // adding Snake#speak (with a supercall)
    +Snake.addMethods({
    +  speak: function($super) {
    +    $super();
    +    alert("You should probably run. He looks really mad.");
    +  }
    +});
    + ringneck.speak();
    +//-> alerts "Ringneck says: hissssssss!"
    +//-> alerts "You should probably run. He looks really mad."
    + // redefining Animal#speak
    +Animal.addMethods({
    +  speak: function() {
    +    alert(this.name + 'snarls: ' + this.sound + '!');
    +  }
    +});
    + ringneck.speak();
    +//-> alerts "Ringneck snarls: hissssssss!"
    +//-> alerts "You should probably run. He looks really mad."
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/date/index.html b/doc/language/date/index.html new file mode 100644 index 000000000..3c9cc7bd5 --- /dev/null +++ b/doc/language/date/index.html @@ -0,0 +1,157 @@ + + + + + Prototype v1.7_rc1 API documentation | Date + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Date +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Date object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/date/prototype/toisostring/index.html b/doc/language/date/prototype/toisostring/index.html new file mode 100644 index 000000000..f06ab27f7 --- /dev/null +++ b/doc/language/date/prototype/toisostring/index.html @@ -0,0 +1,152 @@ + + + + + Prototype v1.7_rc1 API documentation | Date#toISOString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Date#toISOString +

    + + + + +
    +
    +
    +
    +
    +
    Date#toISOString() → String
    + + +

    Produces a string representation of the date in ISO 8601 format. +The time zone is always UTC, as denoted by the suffix "Z".

    + +
    Example
    + +
    var d = new Date(1969, 11, 31, 19);
    +d.getTimezoneOffset();
    +//-> -180 (time offest is given in minutes.)
    +d.toISOString();
    +//-> '1969-12-31T16:00:00Z'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/date/prototype/tojson/index.html b/doc/language/date/prototype/tojson/index.html new file mode 100644 index 000000000..1fc2e38aa --- /dev/null +++ b/doc/language/date/prototype/tojson/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.7_rc1 API documentation | Date#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Date#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Date#toJSON() → String
    + + +

    Internally calls Date#toISOString.

    + +
    Example
    + +
    var d = new Date(1969, 11, 31, 19);
    +d.getTimezoneOffset();
    +//-> -180 (time offest is given in minutes.)
    +d.toJSON();
    +//-> '1969-12-31T16:00:00Z'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/dollara/index.html b/doc/language/dollara/index.html new file mode 100644 index 000000000..e4661c9a4 --- /dev/null +++ b/doc/language/dollara/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | $A + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $A +

    + + + + +
    +
    +
    +
    +
    +
    $A(iterable) → actualArray
    + + +

    Accepts an array-like collection (anything with numeric indices) and returns +its equivalent as an actual Array object. This method is a convenience +alias of Array.from, but is the preferred way of casting to an Array.

    + +

    The primary use of $A is to obtain an actual Array object based on +anything that could pass as an array (e.g. the NodeList or +HTMLCollection objects returned by numerous DOM methods, or the predefined +arguments reference within your functions).

    + +

    The reason you would want an actual Array is simple: +Prototype extends Array to equip it with numerous extra methods, +and also mixes in the Enumerable module, which brings in another +boatload of nifty methods. Therefore, in Prototype, actual Arrays trump +any other collection type you might otherwise get.

    + +

    The conversion performed is rather simple: null, undefined and false become +an empty array; any object featuring an explicit toArray method (as many Prototype +objects do) has it invoked; otherwise, we assume the argument "looks like an array" +(e.g. features a length property and the [] operator), and iterate over its components +in the usual way.

    + +

    When passed an array, $A makes a copy of that array and returns it.

    + +
    Examples
    + +

    The well-known DOM method document.getElementsByTagName() +doesn't return an Array, but a NodeList object that implements the basic array +"interface." Internet Explorer does not allow us to extend Enumerable onto NodeList.prototype, +so instead we cast the returned NodeList to an Array:

    + +
    var paras = $A(document.getElementsByTagName('p'));
    +paras.each(Element.hide);
    +$(paras.last()).show();
    +
    +
    + +

    Notice we had to use each and Element.hide because +$A doesn't perform DOM extensions, since the array could contain +anything (not just DOM elements). To use the Element#hide instance +method we first must make sure all the target elements are extended:

    + +
    $A(document.getElementsByTagName('p')).map(Element.extend).invoke('hide');
    +
    +
    + +

    Want to display your arguments easily? Array features a join method, but the arguments +value that exists in all functions does not inherit from Array. So, the tough +way, or the easy way?

    + +
    // The hard way...
    +function showArgs() {
    +  alert(Array.prototype.join.call(arguments, ', '));
    +}
    + // The easy way...
    +function showArgs() {
    +  alert($A(arguments).join(', '));
    +}
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/dollarh/index.html b/doc/language/dollarh/index.html new file mode 100644 index 000000000..f67e67489 --- /dev/null +++ b/doc/language/dollarh/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | $H + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $H +

    + + + + +
    +
    +
    +
    +
    +
    $H([obj]) → Hash
    + + +

    Creates a Hash (which is synonymous to "map" or "associative array" +for our purposes). A convenience wrapper around the Hash constructor, with a safeguard +that lets you pass an existing Hash object and get it back untouched (instead of +uselessly cloning it).

    + +

    The $H function is the shorter way to obtain a hash (prior to 1.5 final, it was +the only proper way of getting one).

    + +
    Example
    + +
    var h = $H({name: 'John', age: 26, country: 'Australia'});
    +// Equivalent to:
    +var h = new Hash({name: 'John', age: 26, country: 'Australia'});
    +// Can then be accessed the classic Hash way
    +h.get('country');
    +// -> 'Australia'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/dollarr/index.html b/doc/language/dollarr/index.html new file mode 100644 index 000000000..460400ca9 --- /dev/null +++ b/doc/language/dollarr/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | $R + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $R +

    + + + + +
    +
    +
    +
    +
    +
    $R(start, end[, exclusive = false]) → ObjectRange
    + + +

    Creates a new ObjectRange object. This method is a convenience wrapper +around the ObjectRange constructor, but $R is the preferred alias.

    + +

    ObjectRange instances represent a range of consecutive values, be they +numerical, textual, or of another type that semantically supports value +ranges. See the type's documentation for further details, and to discover +how your own objects can support value ranges.

    + +

    The $R function takes exactly the same arguments as the original +constructor: the lower and upper bounds (value of the same, proper +type), and whether the upper bound is exclusive or not. By default, the +upper bound is inclusive.

    + +
    Examples
    + +
    $R(0, 10).include(10)
    +// -> true
    + $A($R(0, 5)).join(', ')
    +// -> '0, 1, 2, 3, 4, 5'
    + $A($R('aa', 'ah')).join(', ')
    +// -> 'aa, ab, ac, ad, ae, af, ag, ah'
    + $R(0, 10, true).include(10)
    +// -> false
    + $R(0, 10, true).each(function(value) {
    +  // invoked 10 times for value = 0 to 9
    +});
    +
    +
    + +

    Note that ObjectRange mixes in the Enumerable module: this makes it +easy to convert a range to an Array (Enumerable provides the +Enumerable#toArray method, which makes the $A conversion +straightforward), or to iterate through values. (Note, however, that getting +the bounds back will be more efficiently done using the +ObjectRange#start and ObjectRange#end properties than calling the +Enumerable#min and Enumerable#max methods).

    + +
    Warning
    + +

    Be careful with String ranges: as described in its String#succ +method, it does not use alphabetical boundaries, but goes all the way +through the character table:

    + +
    $A($R('a', 'e'))
    +// -> ['a', 'b', 'c', 'd', 'e'], no surprise there
    + $A($R('ax', 'ba'))
    +// -> Ouch! Humongous array, starting as ['ax', 'ay', 'az', 'a{', 'a|', 'a}', 'a~'...]
    +
    +
    + +

    See ObjectRange for more information.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/dollarw/index.html b/doc/language/dollarw/index.html new file mode 100644 index 000000000..a7923886d --- /dev/null +++ b/doc/language/dollarw/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | $w + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + utility $w +

    + + + + +
    +
    +
    +
    +
    +
    $w(String) → Array
    + + +

    Splits a string into an Array, treating all whitespace as delimiters. Equivalent +to Ruby's %w{foo bar} or Perl's qw(foo bar).

    + +

    This is one of those life-savers for people who just hate commas in literal arrays :-)

    + +

    Examples

    + +
    $w('apples bananas kiwis')
    +// -> ['apples', 'bananas', 'kiwis']
    +
    +
    + +

    This can slightly shorten code when writing simple iterations:

    + +
    $w('apples bananas kiwis').each(function(fruit){
    +  var message = 'I like ' + fruit
    +  // do something with the message
    +})
    +
    +
    + +

    This also becomes sweet when combined with Element functions:

    + +
    $w('ads navbar funkyLinks').each(Element.hide);
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/index.html b/doc/language/enumerable/index.html new file mode 100644 index 000000000..c288d8517 --- /dev/null +++ b/doc/language/enumerable/index.html @@ -0,0 +1,318 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + mixin Enumerable +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Enumerable provides a large set of useful methods for enumerations — +objects that act as collections of values. It is a cornerstone of +Prototype.

    + +

    Enumerable is a mixin: a set of methods intended not for standaone +use, but for incorporation into other objects.

    + +

    Prototype mixes Enumerable into several classes. The most visible cases +are Array and Hash, but you'll find it in less obvious spots as +well, such as in ObjectRange and various DOM- or Ajax-related objects.

    + +
    The context parameter
    + +

    Every method of Enumerable that takes an iterator also takes the "context +object" as the next (optional) parameter. The context object is what the +iterator will be bound to — what the keyword this will refer to inside +the iterator.

    + +
    var myObject = {};
    + ['foo', 'bar', 'baz'].each(function(name, index) {
    +  this[name] = index;
    +}, myObject); // we have specified the context
    + myObject;
    +// -> { foo: 0, bar: 1, baz: 2}
    +
    +
    + +

    If there is no context argument, the iterator function will execute in +the scope from which the Enumerable method itself was called.

    + +
    Mixing Enumerable into your own objects
    + +

    So, let's say you've created your very own collection-like object (say, +some sort of Set, or perhaps something that dynamically fetches data +ranges from the server side, lazy-loading style). You want to be able to +mix Enumerable in (and we commend you for it). How do you go about this?

    + +

    The Enumerable module basically makes only one requirement on your object: +it must provide a method named _each (note the leading underscore) that +will accept a function as its unique argument, and will contain the actual +"raw iteration" algorithm, invoking its argument with each element in turn.

    + +

    As detailed in the documentation for Enumerable#each, Enumerable +provides all the extra layers (handling iteration short-circuits, passing +numeric indices, etc.). You just need to implement the actual iteration, +as fits your internal structure.

    + +

    If you're still confused, just have a look at the Prototype source code for +Array, Hash, or ObjectRange. They all begin with their own +_each method, which should help you grasp the idea.

    + +

    Once you're done with this, you just need to mix Enumerable in, which +you'll usually do before defining your methods, so as to make sure whatever +overrides you provide for Enumerable methods will indeed prevail. In +short, your code will probably end up looking like this:

    + +
     var YourObject = Class.create(Enumerable, {
    +  initialize: function() { // with whatever constructor arguments you need
    +    // Your construction code
    +  },
    +   _each: function(iterator) {
    +    // Your iteration code, invoking iterator at every turn
    +  },
    +   // Your other methods here, including Enumerable overrides
    +});
    +
    +
    + +

    Then, obviously, your object can be used like this:

    + +
    var obj = new YourObject();
    +// Populate the collection somehow
    +obj.pluck('somePropName');
    +obj.invoke('someMethodName');
    +obj.size();
    +// etc.
    +
    +
    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/all/index.html b/doc/language/enumerable/prototype/all/index.html new file mode 100644 index 000000000..0dc69c66a --- /dev/null +++ b/doc/language/enumerable/prototype/all/index.html @@ -0,0 +1,198 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#all + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#all +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#all([iterator = Prototype.K[, context]]) → Boolean
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Determines whether all the elements are "truthy" (boolean-equivalent to +true), either directly or through computation by the provided iterator. +Stops on the first falsy element found (e.g., the first element that +is boolean-equivalent to false, such as undefined, 0, or indeed +false);

    + +
    Examples
    + +
    [].all();
    +// -> true (empty arrays have no elements that could be falsy)
    + $R(1, 5).all();
    +// -> true (all values in [1..5] are truthy)
    + [0, 1, 2].all();
    +// -> false (with only one loop cycle: 0 is falsy)
    + [9, 10, 15].all(function(n) { return n >= 10; });
    +// -> false (the iterator returns false on 9)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/any/index.html b/doc/language/enumerable/prototype/any/index.html new file mode 100644 index 000000000..30f70f8de --- /dev/null +++ b/doc/language/enumerable/prototype/any/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#any + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#any +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#any([iterator = Prototype.K[, context]]) → Boolean
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Determines whether at least one element is truthy (boolean-equivalent to +true), either directly or through computation by the provided iterator.

    + +
    Examples
    + +
    [].any();
    +// -> false (empty arrays have no elements that could be truthy)
    + $R(0, 2).any();
    +// -> true (on the second loop, 1 is truthy)
    + [2, 4, 6, 8, 10].any(function(n) { return n > 5; });
    +// -> true (the iterator will return true on 6)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/collect/index.html b/doc/language/enumerable/prototype/collect/index.html new file mode 100644 index 000000000..1d7f69ba4 --- /dev/null +++ b/doc/language/enumerable/prototype/collect/index.html @@ -0,0 +1,196 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#collect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#collect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#collect([iterator = Prototype.K[, context]]) → Array
    +
      +
    • + iterator + (Function) + – The iterator function to apply to each element in the enumeration. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns the result of applying iterator to each element. If no +iterator is provided, the elements are simply copied to the +returned array.

    + +
    Examples
    + +
    ['Hitch', "Hiker's", 'Guide', 'to', 'the', 'Galaxy'].collect(function(s) {
    +  return s.charAt(0).toUpperCase();
    +});
    +// -> ['H', 'H', 'G', 'T', 'T', 'G']
    + $R(1,5).collect(function(n) {
    +  return n * n;
    +});
    +// -> [1, 4, 9, 16, 25]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/detect/index.html b/doc/language/enumerable/prototype/detect/index.html new file mode 100644 index 000000000..2d3147205 --- /dev/null +++ b/doc/language/enumerable/prototype/detect/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#detect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#detect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#detect(iterator[, context]) → firstElement | undefined
    +
      +
    • + iterator + (Function) + – The iterator function to apply to each element in the enumeration. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns the first element for which the iterator returns a truthy value. +Aliased by the Enumerable#find method.

    + +
    Example
    + +
    [1, 7, -2, -4, 5].detect(function(n) { return n < 0; });
    +// -> -2
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/each/index.html b/doc/language/enumerable/prototype/each/index.html new file mode 100644 index 000000000..4f62edabc --- /dev/null +++ b/doc/language/enumerable/prototype/each/index.html @@ -0,0 +1,196 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#each + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#each +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#each(iterator[, context]) → Enumerable
    +
      +
    • + iterator + (Function) + – A Function that expects an item in the collection as the first argument and a numerical index as the second. +
    • +
    • + context + (Object) + – The scope in which to call iterator. Affects what the keyword this means inside iterator. +
    • +
    + + +

    Calls iterator for each item in the collection.

    + +
    Examples
    + +
    ['one', 'two', 'three'].each(alert);
    +// Alerts "one", then alerts "two", then alerts "three"
    +
    +
    + +
    Built-In Variants
    + +

    Most of the common use cases for each are already available pre-coded +as other methods on Enumerable. Whether you want to find the first +matching item in an enumeration, or transform it, or determine whether it +has any (or all) values matching a particular condition, Enumerable +has a method to do that for you.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/eachslice/index.html b/doc/language/enumerable/prototype/eachslice/index.html new file mode 100644 index 000000000..145c2a16b --- /dev/null +++ b/doc/language/enumerable/prototype/eachslice/index.html @@ -0,0 +1,204 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#eachSlice + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#eachSlice +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#eachSlice(number[, iterator = Prototype.K[, context]]) → Enumerable
    +
      +
    • + number + (Number) + – The number of items to include in each slice. +
    • +
    • + iterator + (Function) + – An optional function to use to transform each element before it's included in the slice; if this is not provided, the element itself is included. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Groups items into chunks of the given size. The final "slice" may have +fewer than number items; it won't "pad" the last group with empty +values. For that behavior, use Enumerable#inGroupsOf.

    + +
    Example
    + +
    var students = [
    +  { name: 'Sunny', age: 20 },
    +  { name: 'Audrey', age: 21 },
    +  { name: 'Matt', age: 20 },
    +  { name: 'Amelie', age: 26 },
    +  { name: 'Will', age: 21 }
    +];
    + students.eachSlice(3, function(student) {
    +  return student.name;
    +});
    +// -> [['Sunny', 'Audrey', 'Matt'], ['Amelie', 'Will']]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/entries/index.html b/doc/language/enumerable/prototype/entries/index.html new file mode 100644 index 000000000..ba80ea1c0 --- /dev/null +++ b/doc/language/enumerable/prototype/entries/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#entries + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#entries +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#entries() → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/every/index.html b/doc/language/enumerable/prototype/every/index.html new file mode 100644 index 000000000..a42b21258 --- /dev/null +++ b/doc/language/enumerable/prototype/every/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#every + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#every +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#every([iterator = Prototype.K[, context]]) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/filter/index.html b/doc/language/enumerable/prototype/filter/index.html new file mode 100644 index 000000000..74389fd5d --- /dev/null +++ b/doc/language/enumerable/prototype/filter/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#filter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#filter +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#filter(iterator[, context]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/find/index.html b/doc/language/enumerable/prototype/find/index.html new file mode 100644 index 000000000..6df41ff77 --- /dev/null +++ b/doc/language/enumerable/prototype/find/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#find + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#find +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#find(iterator[, context]) → firstElement | undefined
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/findall/index.html b/doc/language/enumerable/prototype/findall/index.html new file mode 100644 index 000000000..48ebddf47 --- /dev/null +++ b/doc/language/enumerable/prototype/findall/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#findAll + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#findAll +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#findAll(iterator[, context]) → Array
    +
      +
    • + iterator + (Function) + – An iterator function to use to test the elements. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns all the elements for which the iterator returned a truthy value. +For the opposite operation, see Enumerable#reject.

    + +
    Example
    + +
    [1, 'two', 3, 'four', 5].findAll(Object.isString);
    +// -> ['two', 'four']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/grep/index.html b/doc/language/enumerable/prototype/grep/index.html new file mode 100644 index 000000000..4fb1ae3bc --- /dev/null +++ b/doc/language/enumerable/prototype/grep/index.html @@ -0,0 +1,206 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#grep + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#grep +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#grep(filter[, iterator = Prototype.K[, context]]) → Array
    +
      +
    • + filter + (RegExp | String | Object) + – The filter to apply to elements. This can be a RegExp instance, a regular expression String, or any object with a match function. +
    • +
    • + iterator + (Function) + – An optional function to apply to selected elements before including them in the result. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns an array containing all of the elements for which the given +filter returns true (or a truthy value). If an iterator is provided, +it is used to produce the returned value for each selected element; this +is done after the element has been selected by the filter.

    + +

    If the given filter is a String, it is converted into a RegExp +object. To select elements, each element is passed into the filter's +match function, which should return a truthy value to select the element +or a falsy value not to. Note that the RegExp match function will +convert elements to Strings to perform matching.

    + +
    Examples
    + +
    // Get all strings containing a repeated letter
    +['hello', 'world', 'this', 'is', 'cool'].grep(/(.)\1/);
    +// -> ['hello', 'cool']
    + // Get all numbers ending with 0 or 5 and subtract 1 from them
    +$R(1, 30).grep(/[05]$/, function(n) { return n - 1; });
    +// -> [4, 9, 14, 19, 24, 29]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/include/index.html b/doc/language/enumerable/prototype/include/index.html new file mode 100644 index 000000000..150fe08d0 --- /dev/null +++ b/doc/language/enumerable/prototype/include/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#include +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#include(object) → Boolean
    +
      +
    • + object + (?) + – The object to look for. +
    • +
    + + +

    Determines whether a given object is in the enumerable or not, +based on the == comparison operator (equality with implicit type +conversion).

    + +
    Examples
    + +
    $R(1, 15).include(10);
    +// -> true
    + ['hello', 'world'].include('HELLO');
    +// -> false ('hello' != 'HELLO')
    + [1, 2, '3', '4', '5'].include(3);
    +// -> true ('3' == 3)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/ingroupsof/index.html b/doc/language/enumerable/prototype/ingroupsof/index.html new file mode 100644 index 000000000..59f8af372 --- /dev/null +++ b/doc/language/enumerable/prototype/ingroupsof/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#inGroupsOf + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inGroupsOf +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inGroupsOf(number[, fillWith = null]) → [group…]
    +
      +
    • + number + (Number) + – The number of items to include in each group. +
    • +
    • + fillWith + (Object) + – An optional filler to use if the last group needs any; defaults to null. +
    • +
    + + +

    Like Enumerable#eachSlice, but pads out the last chunk with the +specified value if necessary and doesn't support the iterator function.

    + +
    Examples
    + +
    var students = [
    +  { name: 'Sunny',  age: 20 },
    +  { name: 'Audrey', age: 21 },
    +  { name: 'Matt',   age: 20 },
    +  { name: 'Amelie', age: 26 },
    +  { name: 'Will',   age: 21 }
    +];
    + students.inGroupsOf(2, { name: '', age: 0 });
    +// -> [
    +//      [{ name: 'Sunny', age: 20 }, { name: 'Audrey', age: 21 }],
    +//      [{ name: 'Matt', age: 20 },  { name: 'Amelie', age: 26 }],
    +//      [{ name: 'Will', age: 21 },  { name: '', age: 0 }]
    +//    ]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/inject/index.html b/doc/language/enumerable/prototype/inject/index.html new file mode 100644 index 000000000..c9a588767 --- /dev/null +++ b/doc/language/enumerable/prototype/inject/index.html @@ -0,0 +1,207 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#inject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inject +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inject(accumulator, iterator[, context]) → accumulatedValue
    +
      +
    • + accumulator + (?) + – The initial value to which the iterator adds. +
    • +
    • + iterator + (Function) + – An iterator function used to build the accumulated result. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Incrementally builds a result value based on the successive results +of the iterator. This can be used for array construction, numerical +sums/averages, etc.

    + +

    The iterator function is called once for each element in the +enumeration, receiving the current value of the accumulator as its first +argument, the element as its second argument, and the element's index as +its third. It returns the new value for the accumulator.

    + +
    Examples
    + +
    $R(1,10).inject(0, function(acc, n) { return acc + n; });
    +// -> 55 (sum of 1 to 10)
    + ['a', 'b', 'c', 'd', 'e'].inject([], function(string, value, index) {
    +  if (index % 2 === 0) { // even numbers
    +    string += value;
    +  }
    +  return string;
    +});
    +// -> 'ace'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/inspect/index.html b/doc/language/enumerable/prototype/inspect/index.html new file mode 100644 index 000000000..a7b97140d --- /dev/null +++ b/doc/language/enumerable/prototype/inspect/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#inspect() → String
    + + +

    Returns the debug-oriented string representation of the object.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/invoke/index.html b/doc/language/enumerable/prototype/invoke/index.html new file mode 100644 index 000000000..9a1da5d83 --- /dev/null +++ b/doc/language/enumerable/prototype/invoke/index.html @@ -0,0 +1,194 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#invoke + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#invoke +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#invoke(methodName[, arg...]) → Array
    +
      +
    • + methodName + (String) + – The name of the method to invoke. +
    • +
    • + args + (?) + – Optional arguments to pass to the method. +
    • +
    + + +

    Invokes the same method, with the same arguments, for all items in a +collection. Returns an array of the results of the method calls.

    + +
    Examples
    + +
    ['hello', 'world'].invoke('toUpperCase');
    +// -> ['HELLO', 'WORLD']
    + ['hello', 'world'].invoke('substring', 0, 3);
    +// -> ['hel', 'wor']
    + $$('input').invoke('stopObserving', 'change');
    +// -> Stops observing the 'change' event on all input elements,
    +// returns an array of the element references.
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/map/index.html b/doc/language/enumerable/prototype/map/index.html new file mode 100644 index 000000000..c5a3b3820 --- /dev/null +++ b/doc/language/enumerable/prototype/map/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#map + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#map +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#map([iterator = Prototype.K[, context]]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/max/index.html b/doc/language/enumerable/prototype/max/index.html new file mode 100644 index 000000000..534ae4bb1 --- /dev/null +++ b/doc/language/enumerable/prototype/max/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#max + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#max +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#max([iterator = Prototype.K[, context]]) → maxValue
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns the maximum element (or element-based iterator result), or +undefined if the enumeration is empty. Elements are either compared +directly, or by first calling iterator and comparing returned values. +If multiple "max" elements (or results) are equivalent, the one closest +to the end of the enumeration is returned.

    + +

    If provided, iterator is called with two arguments: The element being +evaluated, and its index in the enumeration; it should return the value +max should consider (and potentially return).

    + +
    Examples
    + +
    ['c', 'b', 'a'].max();
    +// -> 'c'
    + [1, 3, '3', 2].max();
    +// -> '3' (because both 3 and '3' are "max", and '3' was later)
    + ['zero', 'one', 'two'].max(function(item) { return item.length; });
    +// -> 4
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/member/index.html b/doc/language/enumerable/prototype/member/index.html new file mode 100644 index 000000000..50cea9e85 --- /dev/null +++ b/doc/language/enumerable/prototype/member/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#member + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#member +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#member(object) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/min/index.html b/doc/language/enumerable/prototype/min/index.html new file mode 100644 index 000000000..c4a717dc1 --- /dev/null +++ b/doc/language/enumerable/prototype/min/index.html @@ -0,0 +1,200 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#min + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#min +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#min([iterator = Prototype.K[, context]]) → minValue
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns the minimum element (or element-based iterator result), or +undefined if the enumeration is empty. Elements are either compared +directly, or by first calling iterator and comparing returned values. +If multiple "min" elements (or results) are equivalent, the one closest +to the beginning of the enumeration is returned.

    + +

    If provided, iterator is called with two arguments: The element being +evaluated, and its index in the enumeration; it should return the value +min should consider (and potentially return).

    + +
    Examples
    + +
    ['c', 'b', 'a'].min();
    +// -> 'a'
    + [3, 1, '1', 2].min();
    +// -> 1 (because both 1 and '1' are "min", and 1 was earlier)
    + ['un', 'deux', 'trois'].min(function(item) { return item.length; });
    +// -> 2
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/partition/index.html b/doc/language/enumerable/prototype/partition/index.html new file mode 100644 index 000000000..e16c80d2f --- /dev/null +++ b/doc/language/enumerable/prototype/partition/index.html @@ -0,0 +1,199 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#partition + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#partition +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#partition([iterator = Prototype.K[, context]]) → [TrueArray, FalseArray]
    +
      +
    • + iterator + (Function) + – An optional function to use to evaluate each element in the enumeration; the function should return the value to test. If this is not provided, the element itself is tested. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Partitions the elements in two groups: those regarded as true, and those +considered false. By default, regular JavaScript boolean equivalence +(e.g., truthiness vs. falsiness) is used, but an iterator can be provided +that computes a boolean representation of the elements.

    + +

    Using partition is more efficient than using Enumerable#findAll and +then using Enumerable#reject because the enumeration is only processed +once.

    + +
    Examples
    + +
    ['hello', null, 42, false, true, , 17].partition();
    +// -> [['hello', 42, true, 17], [null, false, undefined]]
    + $R(1, 10).partition(function(n) {
    +  return 0 == n % 2;
    +});
    +// -> [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/pluck/index.html b/doc/language/enumerable/prototype/pluck/index.html new file mode 100644 index 000000000..40a401ed7 --- /dev/null +++ b/doc/language/enumerable/prototype/pluck/index.html @@ -0,0 +1,185 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#pluck + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#pluck +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#pluck(property) → Array
    +
      +
    • + property + (String) + – The name of the property to fetch. +
    • +
    + + +

    Pre-baked implementation for a common use-case of Enumerable#collect +and Enumerable#each: fetching the same property for all of the +elements. Returns an array of the property values.

    + +
    Example
    + +
    ['hello', 'world', 'this', 'is', 'nice'].pluck('length');
    +// -> [5, 5, 4, 2, 4]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/reject/index.html b/doc/language/enumerable/prototype/reject/index.html new file mode 100644 index 000000000..16e57383c --- /dev/null +++ b/doc/language/enumerable/prototype/reject/index.html @@ -0,0 +1,189 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#reject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#reject +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#reject(iterator[, context]) → Array
    +
      +
    • + iterator + (Function) + – An iterator function to use to test the elements. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Returns all the elements for which the iterator returns a falsy value. +For the opposite operation, see Enumerable#findAll.

    + +
    Example
    + +
    [1, "two", 3, "four", 5].reject(Object.isString);
    +// -> [1, 3, 5]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/select/index.html b/doc/language/enumerable/prototype/select/index.html new file mode 100644 index 000000000..cf0a06148 --- /dev/null +++ b/doc/language/enumerable/prototype/select/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#select +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#select(iterator[, context]) → Array
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/size/index.html b/doc/language/enumerable/prototype/size/index.html new file mode 100644 index 000000000..573ea3a59 --- /dev/null +++ b/doc/language/enumerable/prototype/size/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#size + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#size +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#size() → Number
    + + +

    Returns the size of the enumeration.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/some/index.html b/doc/language/enumerable/prototype/some/index.html new file mode 100644 index 000000000..f106b6fdc --- /dev/null +++ b/doc/language/enumerable/prototype/some/index.html @@ -0,0 +1,169 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#some + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#some +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#some([iterator = Prototype.K[, context]]) → Boolean
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/sortby/index.html b/doc/language/enumerable/prototype/sortby/index.html new file mode 100644 index 000000000..5b1732dad --- /dev/null +++ b/doc/language/enumerable/prototype/sortby/index.html @@ -0,0 +1,196 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#sortBy + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#sortBy +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#sortBy(iterator[, context]) → Array
    +
      +
    • + iterator + (Function) + – The function to use to compute the criterion for each element in the enumeration. +
    • +
    • + context + (Object) + – An optional object to use as this within calls to the iterator. +
    • +
    + + +

    Creates a custom-sorted array of the elements based on the criteria +computed, for each element, by the iterator. Computed criteria must have +well-defined ordering semantics (i.e. the < operator must exist between +any two criteria).

    + +

    Enumerable#sortBy does not guarantee a stable sort; adjacent +equivalent elements may be swapped.

    + +
    Example
    + +
    ['hello', 'world', 'this', 'is', 'nice'].sortBy(function(s) {
    +  return s.length;
    +});
    +// -> ['is', 'nice', 'this', 'world', 'hello']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/toarray/index.html b/doc/language/enumerable/prototype/toarray/index.html new file mode 100644 index 000000000..0ab3153af --- /dev/null +++ b/doc/language/enumerable/prototype/toarray/index.html @@ -0,0 +1,178 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#toArray +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#toArray() → Array
    + + +

    Returns an Array containing the elements of the enumeration.

    + +
    Example
    + +
    $R(1, 5).toArray();
    +// -> [1, 2, 3, 4, 5]
    + $H({ name: 'Sunny', age: 20 }).toArray();
    +// -> [['name', 'Sunny'], ['age', 20]]
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/enumerable/prototype/zip/index.html b/doc/language/enumerable/prototype/zip/index.html new file mode 100644 index 000000000..1a04f1eaf --- /dev/null +++ b/doc/language/enumerable/prototype/zip/index.html @@ -0,0 +1,203 @@ + + + + + Prototype v1.7_rc1 API documentation | Enumerable#zip + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Enumerable#zip +

    + + + + +
    +
    +
    +
    +
    +
    Enumerable#zip(sequence...[, iterator = Prototype.K]) → Array
    +
      +
    • + sequence + (Object) + – A sequence to zip with this enumerable (there can be several of these if desired). +
    • +
    • + iterator + (Function) + – Optional function to use to transform the tuples once generated; this is always the last argument provided. +
    • +
    + + +

    Zips together (think of the zipper on a pair of trousers) 2+ sequences, +returning a new array of tuples. Each tuple is an array containing one +value per original sequence. Tuples can be transformed to something else +by applying the optional iterator on them.

    + +

    If supplied, iterator is called with each tuple as its only argument +and should return the value to use in place of that tuple.

    + +
    Examples
    + +
    var firstNames = ['Jane', 'Nitin', 'Guy'];
    +var lastNames  = ['Doe',  'Patel', 'Forcier'];
    +var ages       = [23,     41,      17];
    + firstNames.zip(lastNames);
    +// -> [['Jane', 'Doe'], ['Nitin', 'Patel'], ['Guy', 'Forcier']]
    + firstNames.zip(lastNames, ages);
    +// -> [['Jane', 'Doe', 23], ['Nitin', 'Patel', 41], ['Guy', 'Forcier', 17]]
    + firstNames.zip(lastNames, ages, function(tuple) {
    +  return tuple[0] + ' ' + tuple[1] + ' is ' + tuple[2];
    +});
    +// -> ['Jane Doe is 23', 'Nitin Patel is 41', 'Guy Forcier is 17']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/function/index.html b/doc/language/function/index.html new file mode 100644 index 000000000..dd16c417e --- /dev/null +++ b/doc/language/function/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Function + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Function +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Function object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/language/function/prototype/argumentnames/index.html b/doc/language/function/prototype/argumentnames/index.html new file mode 100644 index 000000000..49d1e642a --- /dev/null +++ b/doc/language/function/prototype/argumentnames/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#argumentNames + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#argumentNames +

    + + + + +
    +
    +
    +
    +
    +
    Function#argumentNames() → Array
    + + +

    Reads the argument names as stated in the function definition and returns +the values as an array of strings (or an empty array if the function is +defined without parameters).

    + +
    Examples
    + +
    function fn(foo, bar) {
    +  return foo + bar;
    +}
    +fn.argumentNames();
    +//-> ['foo', 'bar']
    + Prototype.emptyFunction.argumentNames();
    +//-> []
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/function/prototype/bind/index.html b/doc/language/function/prototype/bind/index.html new file mode 100644 index 000000000..cbb140843 --- /dev/null +++ b/doc/language/function/prototype/bind/index.html @@ -0,0 +1,219 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#bind + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#bind +

    + + + + +
    +
    +
    +
    +
    +
    Function#bind(context[, args...]) → Function
    +
      +
    • + context + (Object) + – The object to bind to. +
    • +
    • + args + (?) + – Optional additional arguments to curry for the function. +
    • +
    + + +

    Binds this function to the given context by wrapping it in another +function and returning the wrapper. Whenever the resulting "bound" +function is called, it will call the original ensuring that this is set +to context. Also optionally curries arguments for the function.

    + +
    Examples
    + +

    A typical use of Function#bind is to ensure that a callback (event +handler, etc.) that is an object method gets called with the correct +object as its context (this value):

    + +
    var AlertOnClick = Class.create({
    +  initialize: function(msg) {
    +    this.msg = msg;
    +  },
    +  handleClick: function(event) {
    +    event.stop();
    +    alert(this.msg);
    +  }
    +});
    +var myalert = new AlertOnClick("Clicked!");
    +$('foo').observe('click', myalert.handleClick); // <= WRONG
    +// -> If 'foo' is clicked, the alert will be blank; "this" is wrong
    +$('bar').observe('click', myalert.handleClick.bind(myalert)); // <= RIGHT
    +// -> If 'bar' is clicked, the alert will be "Clicked!"
    +
    +
    + +

    bind can also curry (burn in) arguments for the function if you +provide them after the context argument:

    + +
    var Averager = Class.create({
    +  initialize: function() {
    +    this.count = 0;
    +    this.total = 0;
    +  },
    +  add: function(addend) {
    +    ++this.count;
    +    this.total += addend;
    +  },
    +  getAverage: function() {
    +    return this.count == 0 ? NaN : this.total / this.count;
    +  }
    +});
    +var a = new Averager();
    +var b = new Averager();
    +var aAdd5 = a.add.bind(a, 5);   // Bind to a, curry 5
    +var aAdd10 = a.add.bind(a, 10); // Bind to a, curry 10
    +var bAdd20 = b.add.bind(b, 20); // Bind to b, curry 20
    +aAdd5();
    +aAdd10();
    +bAdd20();
    +bAdd20();
    +alert(a.getAverage());
    +// -> Alerts "7.5" (average of [5, 10])
    +alert(b.getAverage());
    +// -> Alerts "20" (average of [20, 20])
    +
    +
    + +

    (To curry without binding, see Function#curry.)

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/function/prototype/bindaseventlistener/index.html b/doc/language/function/prototype/bindaseventlistener/index.html new file mode 100644 index 000000000..d5cb66674 --- /dev/null +++ b/doc/language/function/prototype/bindaseventlistener/index.html @@ -0,0 +1,211 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#bindAsEventListener + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#bindAsEventListener +

    + + + + +
    +
    +
    +
    +
    +
    Function#bindAsEventListener(context[, args...]) → Function
    +
      +
    • + context + (Object) + – The object to bind to. +
    • +
    • + args + (?) + – Optional arguments to curry after the event argument. +
    • +
    + + +

    An event-specific variant of Function#bind which ensures the function +will recieve the current event object as the first argument when +executing.

    + +

    It is not necessary to use bindAsEventListener for all bound event +handlers; Function#bind works well for the vast majority of cases. +bindAsEventListener is only needed when:

    + +
      +
    • Using old-style DOM0 handlers rather than handlers hooked up via +Event.observe, because bindAsEventListener gets the event object +from the right place (even on MSIE). (If you're using Event.observe, +that's already handled.)
    • +
    • You want to bind an event handler and curry additional arguments but +have those arguments appear after, rather than before, the event object. +This mostly happens if the number of arguments will vary, and so you +want to know the event object is the first argument.
    • +
    + +
    Example
    + +
    var ContentUpdater = Class.create({
    +  initialize: function(initialData) {
    +    this.data = Object.extend({}, initialData);
    +  },
    +  // On an event, update the content in the elements whose
    +  // IDs are passed as arguments from our data
    +  updateTheseHandler: function(event) {
    +    var argIndex, id, element;
    +    event.stop();
    +    for (argIndex = 1; argIndex < arguments.length; ++argIndex) {
    +      id = arguments[argIndex];
    +      element = $(id);
    +      if (element) {
    +        element.update(String(this.data[id]).escapeHTML());
    +      }
    +    }
    +  }
    +});
    +var cu = new ContentUpdater({
    +  dispName: 'Joe Bloggs',
    +  dispTitle: 'Manager <provisional>',
    +  dispAge: 47
    +});
    +// Using bindAsEventListener because of the variable arg lists:
    +$('btnUpdateName').observe('click',
    +  cu.updateTheseHandler.bindAsEventListener(cu, 'dispName')
    +);
    +$('btnUpdateAll').observe('click',
    +  cu.updateTheseHandler.bindAsEventListener(cu, 'dispName', 'dispTitle', 'dispAge')
    +);
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/function/prototype/curry/index.html b/doc/language/function/prototype/curry/index.html new file mode 100644 index 000000000..0e1debf51 --- /dev/null +++ b/doc/language/function/prototype/curry/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#curry + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#curry +

    + + + + +
    +
    +
    +
    +
    +
    Function#curry(args...) → Function
    +
      +
    • + args + (?) + – The arguments to curry. +
    • +
    + + +

    Curries (burns in) arguments to a function, returning a new function +that when called with call the original passing in the curried arguments +(along with any new ones):

    + +
    function showArguments() {
    +  alert($A(arguments).join(', '));
    +}
    +showArguments(1, 2,, 3);
    +// -> alerts "1, 2, 3"
    + var f = showArguments.curry(1, 2, 3);
    +f('a', 'b');
    +// -> alerts "1, 2, 3, a, b"
    +
    +
    + +

    Function#curry works just like Function#bind without the initial +context argument. Use bind if you need to curry arguments and set +context at the same time.

    + +

    The name "curry" comes from mathematics.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/function/prototype/defer/index.html b/doc/language/function/prototype/defer/index.html new file mode 100644 index 000000000..0d2d0bc39 --- /dev/null +++ b/doc/language/function/prototype/defer/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#defer + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#defer +

    + + + + +
    +
    +
    +
    +
    +
    Function#defer(args...) → Number
    +
      +
    • + args + (?) + – Optional arguments to pass into the function. +
    • +
    + + +

    Schedules the function to run as soon as the interpreter is idle.

    + +

    A "deferred" function will not run immediately; rather, it will run as soon +as the interpreter's call stack is empty.

    + +

    Behaves much like window.setTimeout with a delay set to 0. Returns an +ID that can be used to clear the timeout with window.clearTimeout before +it runs.

    + +
    Example
    + +
    function showMsg(msg) {
    +  alert(msg);
    +}
    + showMsg("One");
    +showMsg.defer("Two");
    +showMsg("Three");
    +// Alerts "One", then "Three", then (after a brief pause) "Two"
    +// Note that "Three" happens before "Two"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/function/prototype/delay/index.html b/doc/language/function/prototype/delay/index.html new file mode 100644 index 000000000..3b1e769af --- /dev/null +++ b/doc/language/function/prototype/delay/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#delay + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#delay +

    + + + + +
    +
    +
    +
    +
    +
    Function#delay(timeout[, args...]) → Number
    +
      +
    • + timeout + (Number) + – The time, in seconds, to wait before calling the function. +
    • +
    • + args + (?) + – Optional arguments to pass to the function when calling it. +
    • +
    + + +

    Schedules the function to run after the specified amount of time, passing +any arguments given.

    + +

    Behaves much like window.setTimeout, but the timeout is in seconds +rather than milliseconds. Returns an integer ID that can be used to +clear the timeout with window.clearTimeout before it runs.

    + +

    To schedule a function to run as soon as the interpreter is idle, use +Function#defer.

    + +
    Example
    + +
    function showMsg(msg) {
    +  alert(msg);
    +}
    +showMsg.delay(0.1, "Hi there!");
    +// -> Waits a 10th of a second, then alerts "Hi there!"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/function/prototype/methodize/index.html b/doc/language/function/prototype/methodize/index.html new file mode 100644 index 000000000..649e453a7 --- /dev/null +++ b/doc/language/function/prototype/methodize/index.html @@ -0,0 +1,193 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#methodize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#methodize +

    + + + + +
    +
    +
    +
    +
    +
    Function#methodize() → Function
    + + +

    Wraps the function inside another function that, when called, pushes +this to the original function as the first argument (with any further +arguments following it).

    + +

    The methodize method transforms the original function that has an +explicit first argument to a function that passes this (the current +context) as an implicit first argument at call time. It is useful when we +want to transform a function that takes an object to a method of that +object or its prototype, shortening its signature by one argument.

    + +
    Example
    + +
    // A function that sets a name on a target object
    +function setName(target, name) {
    +  target.name = name;
    +}
    + // Use it
    +obj = {};
    +setName(obj, 'Fred');
    +obj.name;
    +// -> "Fred"
    + // Make it a method of the object
    +obj.setName = setName.methodize();
    + // Use the method instead
    +obj.setName('Barney');
    +obj.name;
    +// -> "Barney"
    +
    +
    + +

    The example above is quite simplistic. It's more useful to copy methodized +functions to object prototypes so that new methods are immediately shared +among instances. In the Prototype library, methodize is used in various +places such as the DOM module, so that (for instance) you can hide an +element either by calling the static version of Element.hide and passing in +an element reference or ID, like so:

    + +
    Element.hide('myElement');
    +
    +
    + +

    ...or if you already have an element reference, just calling the +methodized form instead:

    + +
    myElement.hide();
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/function/prototype/wrap/index.html b/doc/language/function/prototype/wrap/index.html new file mode 100644 index 000000000..4a33f7a06 --- /dev/null +++ b/doc/language/function/prototype/wrap/index.html @@ -0,0 +1,191 @@ + + + + + Prototype v1.7_rc1 API documentation | Function#wrap + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Function#wrap +

    + + + + +
    +
    +
    +
    +
    +
    Function#wrap(wrapper) → Function
    +
      +
    • + wrapper + (Function) + – The function to use as a wrapper. +
    • +
    + + +

    Returns a function "wrapped" around the original function.

    + +

    Function#wrap distills the essence of aspect-oriented programming into +a single method, letting you easily build on existing functions by +specifying before and after behavior, transforming the return value, or +even preventing the original function from being called.

    + +

    The wraper function is called with this signature:

    + +
    function wrapper(callOriginal[, args...])
    +
    +
    + +

    ...where callOriginal is a function that can be used to call the +original (wrapped) function (or not, as appropriate). (callOriginal is +not a direct reference to the original function, there's a layer of +indirection in-between that sets up the proper context [this value] for +it.)

    + +
    Example
    + +
    // Wrap String#capitalize so it accepts an additional argument
    +String.prototype.capitalize = String.prototype.capitalize.wrap(
    +  function(callOriginal, eachWord) {
    +    if (eachWord && this.include(" ")) {
    +      // capitalize each word in the string
    +      return this.split(" ").invoke("capitalize").join(" ");
    +    } else {
    +      // proceed using the original function
    +      return callOriginal();
    +    }
    +  });
    + "hello world".capitalize();
    +// -> "Hello world" (only the 'H' is capitalized)
    +"hello world".capitalize(true);
    +// -> "Hello World" (both 'H' and 'W' are capitalized)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/index.html b/doc/language/hash/index.html new file mode 100644 index 000000000..d4ce9ca42 --- /dev/null +++ b/doc/language/hash/index.html @@ -0,0 +1,221 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Hash +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A set of key/value pairs.

    + +

    Hash can be thought of as an associative array, binding unique keys to +values (which are not necessarily unique), though it can not guarantee +consistent order its elements when iterating. Because of the nature of +JavaScript, every object is in fact a hash; but Hash adds a number of +methods that let you enumerate keys and values, iterate over key/value +pairs, merge two hashes together, and much more.

    + +
    Creating a hash
    + +

    You can create a Hash either via new Hash() or the convenience alias +$H(); there is *no* difference between them. In either case, you may +optionally pass in an object to seed the Hash. If you pass in a Hash, +it will be cloned.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Hash

    +
    +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/hash/new/index.html b/doc/language/hash/new/index.html new file mode 100644 index 000000000..f3fa9af5f --- /dev/null +++ b/doc/language/hash/new/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | new Hash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Hash +

    + + + + +
    +
    +
    +
    +
    +
    new([object])
    + + +

    Creates a new Hash. If object is given, the new hash will be populated +with all the object's properties. See $H.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/clone/index.html b/doc/language/hash/prototype/clone/index.html new file mode 100644 index 000000000..76f5ea325 --- /dev/null +++ b/doc/language/hash/prototype/clone/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#clone +

    + + + + +
    +
    +
    +
    +
    +
    Hash#clone() → Hash
    + + +

    Returns a clone of this Hash.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/each/index.html b/doc/language/hash/prototype/each/index.html new file mode 100644 index 000000000..b245f342d --- /dev/null +++ b/doc/language/hash/prototype/each/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#each + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#each +

    + + + + +
    +
    +
    +
    +
    +
    Hash#each(iterator[, context]) → Hash
    +
      +
    • + iterator + (Function) + – A function that expects each item in the Hash as the first argument and a numerical index as the second. +
    • +
    • + context + (Object) + – The scope in which to call iterator. Determines what this means inside iterator. +
    • +
    + + +

    Iterates over the name/value pairs in the hash.

    + +

    This is actually just the #each method from the +mixed-in Enumerable module. It is documented here to describe the +structure of the elements passed to the iterator and the order of +iteration.

    + +

    The iterator's first argument (the "item") is an object with two +properties:

    + +
      +
    • key: the key name as a String
    • +
    • value: the corresponding value (which may be undefined)
    • +
    + +

    The order of iteration is implementation-dependent, as it relies on +the order of the native for..in loop. Although most modern +implementations exhibit ordered behavior, this is not standardized and +may not always be the case, and so cannot be relied upon.

    + +
    Example
    + +
    var h = $H({version: 1.6, author: 'The Core Team'});
    + h.each(function(pair) {
    +  alert(pair.key + ' = "' + pair.value + '"');
    +});
    +// Alerts 'version = "1.6"' and 'author = "The Core Team"'
    +// -or-
    +// Alerts 'author = "The Core Team"' and 'version = "1.6"'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/get/index.html b/doc/language/hash/prototype/get/index.html new file mode 100644 index 000000000..bfc626680 --- /dev/null +++ b/doc/language/hash/prototype/get/index.html @@ -0,0 +1,163 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#get + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#get +

    + + + + +
    +
    +
    +
    +
    +
    Hash#get(key) → value
    + + +

    Returns the stored value for the given key.

    + +
    Examples
    + +
    var h = new Hash({a: 'apple', b: 'banana', c: 'coconut'});
    +h.get('a');
    +// -> 'apple'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/index/index.html b/doc/language/hash/prototype/index/index.html new file mode 100644 index 000000000..e5f34095e --- /dev/null +++ b/doc/language/hash/prototype/index/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#index + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#index +

    + + + + +
    +
    +
    +
    +
    +
    Hash#index(value) → String
    + + +

    Returns the first key in the hash whose value matches value. +Returns false if there is no such key.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/inspect/index.html b/doc/language/hash/prototype/inspect/index.html new file mode 100644 index 000000000..b4a7cf497 --- /dev/null +++ b/doc/language/hash/prototype/inspect/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#inspect +

    + + + + +
    +
    +
    +
    +
    +
    Hash#inspect() → String
    + + +

    Returns the debug-oriented string representation of the Hash.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/keys/index.html b/doc/language/hash/prototype/keys/index.html new file mode 100644 index 000000000..d8ba6a60a --- /dev/null +++ b/doc/language/hash/prototype/keys/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#keys + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#keys +

    + + + + +
    +
    +
    +
    +
    +
    Hash#keys() → [String…]
    + + +

    Provides an Array containing the keys for items stored in the hash.

    + +

    The order of the keys is not guaranteed.

    + +
    Example
    + +
    var h = $H({one: "uno", two: "due", three: "tre"});
    +h.keys();
    +// -> ["one", "three", "two"] (these may be in any order)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/merge/index.html b/doc/language/hash/prototype/merge/index.html new file mode 100644 index 000000000..50bc41e80 --- /dev/null +++ b/doc/language/hash/prototype/merge/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#merge + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#merge +

    + + + + +
    +
    +
    +
    +
    +
    Hash#merge(object) → Hash
    +
      +
    • + object + (Object | Hash) + – The object to merge with this hash to produce the resulting hash. +
    • +
    + + +

    Returns a new Hash instance with object's key/value pairs merged in; +this hash remains unchanged.

    + +

    To modify the original hash in place, use Hash#update.

    + +
    Example
    + +
    var h = $H({one: "uno", two: "due"});
    +var h2 = h.merge({three: "tre"});
    +h.keys();
    +// -> ["one", "two"] (unchanged)
    +h2.keys();
    +// -> ["one", "two", "three"] (has merged contents)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/set/index.html b/doc/language/hash/prototype/set/index.html new file mode 100644 index 000000000..165b091fd --- /dev/null +++ b/doc/language/hash/prototype/set/index.html @@ -0,0 +1,181 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#set + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#set +

    + + + + +
    +
    +
    +
    +
    +
    Hash#set(key, value) → value
    +
      +
    • + key + (String) + – The key to use for this value. +
    • +
    • + value + (?) + – The value to use for this key. +
    • +
    + + +

    Stores value in the hash using the key key and returns value.

    + +
    Example
    + +
    var h = $H();
    +h.keys();
    +// -> [] (initially empty)
    +h.set('a', 'apple');
    +// -> "apple"
    +h.keys();
    +// -> ["a"] (has the new entry)
    +h.get('a');
    +// -> "apple"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/tojson/index.html b/doc/language/hash/prototype/tojson/index.html new file mode 100644 index 000000000..d5a350a24 --- /dev/null +++ b/doc/language/hash/prototype/tojson/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toJSON() → Object
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/toobject/index.html b/doc/language/hash/prototype/toobject/index.html new file mode 100644 index 000000000..e44e8bb07 --- /dev/null +++ b/doc/language/hash/prototype/toobject/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#toObject + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toObject +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toObject() → Object
    + + +

    Returns a cloned, vanilla object whose properties (and property values) +match the keys (and values) from the hash.

    + +
    Example
    + +
    var h = new Hash({ a: 'apple', b: 'banana', c: 'coconut' });
    +var obj = h.toObject();
    +obj.a;
    +// -> "apple"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/toquerystring/index.html b/doc/language/hash/prototype/toquerystring/index.html new file mode 100644 index 000000000..6bd851642 --- /dev/null +++ b/doc/language/hash/prototype/toquerystring/index.html @@ -0,0 +1,191 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#toQueryString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toQueryString +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toQueryString() → String
    + + +

    Returns a URL-encoded string containing the hash's contents as query +parameters according to the following rules:

    + +
      +
    • An undefined value results a parameter with no value portion at all +(simply the key name, no equal sign).
    • +
    • A null value results a parameter with a blank value (the key followed +by an equal sign and nothing else).
    • +
    • A boolean value results a parameter with the value "true" or "false".
    • +
    • An Array value results in a parameter for each array element, in +array order, each using the same key.
    • +
    • All keys and values are URI-encoded using JavaScript's native +encodeURIComponent function.
    • +
    + +

    The order of pairs in the string is not guaranteed, other than the order +of array values described above.

    + +
    Example
    + +
    $H({action: 'ship',
    +    order_id: 123,
    +    fees: ['f1', 'f2']
    +}).toQueryString();
    +// -> "action=ship&order_id=123&fees=f1&fees=f2"
    + $H({comment: '',
    +    'key with spaces': true,
    +    related_order: undefined,
    +    contents: null,
    +    'label': 'a demo'
    +}).toQueryString();
    +// -> "comment=&key%20with%20spaces=true&related_order&contents=&label=a%20demo"
    + // an empty hash is an empty query string:
    +$H().toQueryString();
    +// -> ""
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/totemplatereplacements/index.html b/doc/language/hash/prototype/totemplatereplacements/index.html new file mode 100644 index 000000000..dfbf88abb --- /dev/null +++ b/doc/language/hash/prototype/totemplatereplacements/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#toTemplateReplacements + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#toTemplateReplacements +

    + + + + +
    +
    +
    +
    +
    +
    Hash#toTemplateReplacements() → Object
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/unset/index.html b/doc/language/hash/prototype/unset/index.html new file mode 100644 index 000000000..78abb3506 --- /dev/null +++ b/doc/language/hash/prototype/unset/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#unset + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#unset +

    + + + + +
    +
    +
    +
    +
    +
    Hash#unset(key) → value
    + + +

    Deletes the stored pair for the given key from the hash and returns its +value.

    + +
    Example
    + +
    var h = new Hash({a: 'apple', b: 'banana', c: 'coconut'});
    +h.keys();
    +// -> ["a", "b", "c"]
    +h.unset('a');
    +// -> 'apple'
    +h.keys();
    +// -> ["b", "c"] ("a" is no longer in the hash)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/update/index.html b/doc/language/hash/prototype/update/index.html new file mode 100644 index 000000000..573ce267f --- /dev/null +++ b/doc/language/hash/prototype/update/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#update + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#update +

    + + + + +
    +
    +
    +
    +
    +
    Hash#update(object) → Hash
    +
      +
    • + object + (Object | Hash) + – The object to merge with this hash to produce the resulting hash. +
    • +
    + + +

    Updates a hash in place with the key/value pairs of object, returns +the hash.

    + +

    Hash#update modifies the hash. To get a new hash instead, use +Hash#merge.

    + +
    Example
    + +
    var h = $H({one: "uno", two: "due"});
    +h.update({three: "tre"});
    +// -> h (a reference to the original hash)
    +h.keys();
    +// -> ["one", "two", "three"] (has merged contents)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/hash/prototype/values/index.html b/doc/language/hash/prototype/values/index.html new file mode 100644 index 000000000..c4d39657f --- /dev/null +++ b/doc/language/hash/prototype/values/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Hash#values + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Hash#values +

    + + + + +
    +
    +
    +
    +
    +
    Hash#values() → Array
    + + +

    Collects the values of the hash and returns them in an array.

    + +

    The order of the values is not guaranteed.

    + +
    Example
    + +
    var h = $H({one: "uno", two: "due", three: "tre"});
    +h.values();
    +// -> ["uno", "tre", "due"] (these may be in any order)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/index.html b/doc/language/index.html new file mode 100644 index 000000000..b6c744151 --- /dev/null +++ b/doc/language/index.html @@ -0,0 +1,229 @@ + + + + + Prototype v1.7_rc1 API documentation | Language section + + + + + + + + + + + + + + + + +
    + +
    + + + + + + +

    + section Language section +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Additions to JavaScript's "standard library" and extensions to +built-in JavaScript objects.

    +
    +
    + + + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Try

      + +
    • +
    • +

      Prototype

      + +

      The Prototype namespace provides fundamental information about the +Prototype library you're using, as well as a central repository for default +iterators or functions.

      +
    • +
    +
    +
    + + +
    +
    +

    Classes

    +
    +
    + +
      +
    • +

      Array

      + +

      Prototype extends all native JavaScript arrays with quite a few powerful +methods.

      +
    • +
    • +

      Class

      + +

      Manages Prototype's class-based OOP system.

      +
    • +
    • +

      Date

      + +

      Extensions to the built-in Date object.

      +
    • +
    • +

      Function

      + +

      Extensions to the built-in Function object.

      +
    • +
    • +

      Hash

      + +

      A set of key/value pairs.

      +
    • +
    • +

      Number

      + +

      Extensions to the built-in Number object.

      +
    • +
    • +

      Object

      + +

      Extensions to the built-in Object object.

      +
    • +
    • +

      ObjectRange

      + +

      A succession of values.

      +
    • +
    • +

      PeriodicalExecuter

      + +

      Oversees the calling of a particular function periodically.

      +
    • +
    • +

      RegExp

      + +

      Extensions to the built-in RegExp object.

      +
    • +
    • +

      String

      + +

      Extensions to the built-in String class.

      +
    • +
    • +

      Template

      + +

      A class for sophisticated string interpolation.

      +
    • +
    +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/number/index.html b/doc/language/number/index.html new file mode 100644 index 000000000..18e5906eb --- /dev/null +++ b/doc/language/number/index.html @@ -0,0 +1,185 @@ + + + + + Prototype v1.7_rc1 API documentation | Number + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Number +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Number object.

    + +

    Prototype extends native JavaScript numbers in order to provide:

    + + +
    +
    + + + + + + + + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/number/prototype/abs/index.html b/doc/language/number/prototype/abs/index.html new file mode 100644 index 000000000..7039b322d --- /dev/null +++ b/doc/language/number/prototype/abs/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#abs + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#abs +

    + + + + +
    +
    +
    +
    +
    +
    Number#abs() → Number
    + + +

    Returns the absolute value of the number. Convenience method that simply +calls Math.abs on this instance and returns the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/number/prototype/ceil/index.html b/doc/language/number/prototype/ceil/index.html new file mode 100644 index 000000000..007a6ddc4 --- /dev/null +++ b/doc/language/number/prototype/ceil/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#ceil + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#ceil +

    + + + + +
    +
    +
    +
    +
    +
    Number#ceil() → Number
    + + +

    Returns the smallest integer greater than or equal to the number. +Convenience method that simply calls Math.ceil on this instance and +returns the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/number/prototype/floor/index.html b/doc/language/number/prototype/floor/index.html new file mode 100644 index 000000000..be5e724bb --- /dev/null +++ b/doc/language/number/prototype/floor/index.html @@ -0,0 +1,149 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#floor + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#floor +

    + + + + +
    +
    +
    +
    +
    +
    Number#floor() → Number
    + + +

    Returns the largest integer less than or equal to the number. +Convenience method that simply calls Math.floor on this instance and +returns the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/number/prototype/round/index.html b/doc/language/number/prototype/round/index.html new file mode 100644 index 000000000..e3fc2733f --- /dev/null +++ b/doc/language/number/prototype/round/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#round + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#round +

    + + + + +
    +
    +
    +
    +
    +
    Number#round() → Number
    + + +

    Rounds the number to the nearest integer. Convenience method that simply +calls Math.round on this instance and returns the result.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/number/prototype/succ/index.html b/doc/language/number/prototype/succ/index.html new file mode 100644 index 000000000..c60e2d034 --- /dev/null +++ b/doc/language/number/prototype/succ/index.html @@ -0,0 +1,148 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#succ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#succ +

    + + + + +
    +
    +
    +
    +
    +
    Number#succ() → Number
    + + +

    Returns the successor of the current Number, as defined by current + 1. +Used to make numbers compatible with ObjectRange.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/number/prototype/times/index.html b/doc/language/number/prototype/times/index.html new file mode 100644 index 000000000..ce3923945 --- /dev/null +++ b/doc/language/number/prototype/times/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#times + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#times +

    + + + + +
    +
    +
    +
    +
    +
    Number#times(iterator[,context]) → Number
    +
      +
    • + iterator + (Function) + – An iterator function to call. +
    • +
    • + context + (Object) + – An optional context (this value) to use when calling iterator. +
    • +
    + + +

    Calls iterator the specified number of times, passing in a number as +the first parameter. The number will be 0 on first call, 1 on second +call, etc. times returns the number instance it was called on.

    + +
    Example
    + +
    (3).times(alert);
    +// -> Alerts "0", then "1", then "2"; returns 3
    + var obj = {count: 0, total: 0};
    +function add(addend) {
    +  ++this.count;
    +  this.total += addend;
    +}
    +(4).times(add, obj);
    +// -> 4
    +obj.count;
    +// -> 4
    +obj.total;
    +// -> 6 (e.g., 0 + 1 + 2 + 3)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/number/prototype/tocolorpart/index.html b/doc/language/number/prototype/tocolorpart/index.html new file mode 100644 index 000000000..a0ebcfed1 --- /dev/null +++ b/doc/language/number/prototype/tocolorpart/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#toColorPart + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#toColorPart +

    + + + + +
    +
    +
    +
    +
    +
    Number#toColorPart() → String
    + + +

    Produces a 2-digit hexadecimal representation of the number +(which is therefore assumed to be in the [0..255] range, inclusive). +Useful for composing CSS color strings.

    + +
    Example
    + +
    10.toColorPart()
    +// -> "0a"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/number/prototype/topaddedstring/index.html b/doc/language/number/prototype/topaddedstring/index.html new file mode 100644 index 000000000..8470de336 --- /dev/null +++ b/doc/language/number/prototype/topaddedstring/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Number#toPaddedString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Number#toPaddedString +

    + + + + +
    +
    +
    +
    +
    +
    Number#toPaddedString(length[, radix]) → String
    +
      +
    • + length + (Number) + – The minimum length for the resulting string. +
    • +
    • + radix + (Number) + – An optional radix for the string representation, defaults to 10 (decimal). +
    • +
    + + +

    Returns a string representation of the number padded with leading 0s so +that the string's length is at least equal to length. Takes an optional +radix argument which specifies the base to use for conversion.

    + +
    Examples
    + +
    (13).toPaddedString(4);
    +// -> "0013"
    + (13).toPaddedString(2);
    +// -> "13"
    + (13).toPaddedString(1);
    +// -> "13"
    + (13).toPaddedString(4, 16)
    +// -> "000d"
    + (13).toPaddedString(4, 2);
    +// -> "1101"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/clone/index.html b/doc/language/object/clone/index.html new file mode 100644 index 000000000..d27f0ef84 --- /dev/null +++ b/doc/language/object/clone/index.html @@ -0,0 +1,188 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.clone + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.clone +

    + + + + +
    +
    +
    +
    +
    +
    Object.clone(object) → Object
    +
      +
    • + object + (Object) + – The object to clone. +
    • +
    + + +

    Creates and returns a shallow duplicate of the passed object by copying +all of the original's key/value pairs onto an empty object.

    + +

    Do note that this is a shallow copy, not a deep copy. Nested objects +will retain their references.

    + +
    Examples
    + +
    var original = {name: 'primaryColors', values: ['red', 'green', 'blue']};
    +var copy = Object.clone(original);
    + original.name;
    +// -> "primaryColors"
    +original.values[0];
    +// -> "red"
    +copy.name;
    +// -> "primaryColors"
    + copy.name = "secondaryColors";
    +original.name;
    +// -> "primaryColors"
    +copy.name;
    +// -> "secondaryColors"
    + copy.values[0] = 'magenta';
    +copy.values[1] = 'cyan';
    +copy.values[2] = 'yellow';
    +original.values[0];
    +// -> "magenta" (it's a shallow copy, so they share the array)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/extend/index.html b/doc/language/object/extend/index.html new file mode 100644 index 000000000..2bdc2e229 --- /dev/null +++ b/doc/language/object/extend/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.extend + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.extend +

    + + + + +
    +
    +
    +
    +
    +
    Object.extend(destination, source) → Object
    +
      +
    • + destination + (Object) + – The object to receive the new properties. +
    • +
    • + source + (Object) + – The object whose properties will be duplicated. +
    • +
    + + +

    Copies all properties from the source to the destination object. Used by Prototype +to simulate inheritance (rather statically) by copying to prototypes.

    + +

    Documentation should soon become available that describes how Prototype implements +OOP, where you will find further details on how Prototype uses Object.extend and +Class.create (something that may well change in version 2.0). It will be linked +from here.

    + +

    Do not mistake this method with its quasi-namesake Element.extend, +which implements Prototype's (much more complex) DOM extension mechanism.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/index.html b/doc/language/object/index.html new file mode 100644 index 000000000..8f5a807cc --- /dev/null +++ b/doc/language/object/index.html @@ -0,0 +1,212 @@ + + + + + Prototype v1.7_rc1 API documentation | Object + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Object +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in Object object.

    + +

    Because it is dangerous and invasive to augment Object.prototype (i.e., +add instance methods to objects), all these methods are static methods that +take an Object as their first parameter.

    + +

    Object is used by Prototype as a namespace; that is, it just keeps a few +new methods together, which are intended for namespaced access (i.e. starting +with "Object.").

    + +

    For the regular developer (who simply uses Prototype without tweaking it), the +most commonly used methods are probably Object.inspect and, to a lesser degree, +Object.clone.

    + +

    Advanced users, who wish to create their own objects like Prototype does, or +explore objects as if they were hashes, will turn to Object.extend, +Object.keys, and Object.values.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/language/object/inspect/index.html b/doc/language/object/inspect/index.html new file mode 100644 index 000000000..e21678949 --- /dev/null +++ b/doc/language/object/inspect/index.html @@ -0,0 +1,187 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.inspect +

    + + + + +
    +
    +
    +
    +
    +
    Object.inspect(obj) → String
    +
      +
    • + object + (Object) + – The item to be inspected. +
    • +
    + + +

    Returns the debug-oriented string representation of the object.

    + +
      +
    • undefined and null are represented as such.
    • +
    • Other types are looked up for a inspect method: if there is one, it is used, otherwise, +it reverts to the toString method.
    • +
    + +

    Prototype provides inspect methods for many types, both built-in and library-defined, +such as in String#inspect, Array#inspect, Enumerable#inspect and Hash#inspect, +which attempt to provide most-useful string representations (from a developer's standpoint) +for their respective types.

    + +
    Examples
    + +
    Object.inspect();
    +// -> 'undefined'
    + Object.inspect(null);
    +// -> 'null'
    + Object.inspect(false);
    +// -> 'false'
    + Object.inspect([1, 2, 3]);
    +// -> '[1, 2, 3]'
    + Object.inspect('hello');
    +// -> "'hello'"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/isarray/index.html b/doc/language/object/isarray/index.html new file mode 100644 index 000000000..8da7f0ed4 --- /dev/null +++ b/doc/language/object/isarray/index.html @@ -0,0 +1,172 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isArray +

    + + + + +
    +
    +
    +
    +
    +
    Object.isArray(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is an Array; false otherwise.

    + +
    Examples
    + +
    Object.isArray([]);
    +//-> true
    + Object.isArray($w());
    +//-> true
    + Object.isArray({ });
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/iselement/index.html b/doc/language/object/iselement/index.html new file mode 100644 index 000000000..a53aea319 --- /dev/null +++ b/doc/language/object/iselement/index.html @@ -0,0 +1,174 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isElement + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isElement +

    + + + + +
    +
    +
    +
    +
    +
    Object.isElement(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is a DOM node of type 1; false otherwise.

    + +
    Examples
    + +
    Object.isElement(new Element('div'));
    +//-> true
    + Object.isElement(document.createElement('div'));
    +//-> true
    + Object.isElement($('id_of_an_exiting_element'));
    +//-> true
    + Object.isElement(document.createTextNode('foo'));
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/isfunction/index.html b/doc/language/object/isfunction/index.html new file mode 100644 index 000000000..95a70279b --- /dev/null +++ b/doc/language/object/isfunction/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isFunction + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isFunction +

    + + + + +
    +
    +
    +
    +
    +
    Object.isFunction(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type Function; false otherwise.

    + +
    Examples
    + +
    Object.isFunction($);
    +//-> true
    + Object.isFunction(123);
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/ishash/index.html b/doc/language/object/ishash/index.html new file mode 100644 index 000000000..cfd846065 --- /dev/null +++ b/doc/language/object/ishash/index.html @@ -0,0 +1,173 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isHash + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isHash +

    + + + + +
    +
    +
    +
    +
    +
    Object.isHash(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is an instance of the Hash class; false +otherwise.

    + +
    Examples
    + +
    Object.isHash(new Hash({ }));
    +//-> true
    + Object.isHash($H({ }));
    +//-> true
    + Object.isHash({ });
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/isnumber/index.html b/doc/language/object/isnumber/index.html new file mode 100644 index 000000000..37f13be8e --- /dev/null +++ b/doc/language/object/isnumber/index.html @@ -0,0 +1,172 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isNumber + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isNumber +

    + + + + +
    +
    +
    +
    +
    +
    Object.isNumber(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type Number; false otherwise.

    + +
    Examples
    + +
    Object.isNumber(0);
    +//-> true
    + Object.isNumber(1.2);
    +//-> true
    + Object.isNumber("foo");
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/isstring/index.html b/doc/language/object/isstring/index.html new file mode 100644 index 000000000..1ef3c34db --- /dev/null +++ b/doc/language/object/isstring/index.html @@ -0,0 +1,172 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isString +

    + + + + +
    +
    +
    +
    +
    +
    Object.isString(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type String; false otherwise.

    + +
    Examples
    + +
    Object.isString("foo");
    +//-> true
    + Object.isString("");
    +//-> true
    + Object.isString(123);
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/isundefined/index.html b/doc/language/object/isundefined/index.html new file mode 100644 index 000000000..acaa0c533 --- /dev/null +++ b/doc/language/object/isundefined/index.html @@ -0,0 +1,176 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.isUndefined + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.isUndefined +

    + + + + +
    +
    +
    +
    +
    +
    Object.isUndefined(object) → Boolean
    +
      +
    • + object + (Object) + – The object to test. +
    • +
    + + +

    Returns true if object is of type undefined; false otherwise.

    + +
    Examples
    + +
    Object.isUndefined();
    +//-> true
    + Object.isUndefined(undefined);
    +//-> true
    + Object.isUndefined(null);
    +//-> false
    + Object.isUndefined(0);
    +//-> false
    + Object.isUndefined("");
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/keys/index.html b/doc/language/object/keys/index.html new file mode 100644 index 000000000..dd71dfa0e --- /dev/null +++ b/doc/language/object/keys/index.html @@ -0,0 +1,175 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.keys + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.keys +

    + + + + +
    +
    +
    +
    +
    +
    Object.keys(object) → Array
    +
      +
    • + object + (Object) + – The object to pull keys from. +
    • +
    + + +

    Returns an array of the object's property names.

    + +

    Note that the order of the resulting array is browser-dependent — it +relies on the for...in loop, for which the ECMAScript spec does not +prescribe an enumeration order. Sort the resulting array if you wish to +normalize the order of the object keys.

    + +
    Examples
    + +
    Object.keys();
    +// -> []
    + Object.keys({ name: 'Prototype', version: '1.6.1' }).sort();
    +// -> ['name', 'version']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/tohtml/index.html b/doc/language/object/tohtml/index.html new file mode 100644 index 000000000..0f13445bf --- /dev/null +++ b/doc/language/object/tohtml/index.html @@ -0,0 +1,195 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.toHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toHTML +

    + + + + +
    +
    +
    +
    +
    +
    Object.toHTML(object) → String
    +
      +
    • + object + (Object) + – The object to convert to HTML. +
    • +
    + + +

    Converts the object to its HTML representation.

    + +

    Returns the return value of object's toHTML method if it exists; else +runs object through String.interpret.

    + +
    Examples
    + +
    var Bookmark = Class.create({
    +  initialize: function(name, url) {
    +    this.name = name;
    +    this.url = url;
    +  },
    +   toHTML: function() {
    +    return '<a href="#{url}">#{name}</a>'.interpolate(this);
    +  }
    +});
    + var api = new Bookmark('Prototype API', 'http://prototypejs.org/api');
    + Object.toHTML(api);
    +//-> '<a href="http://prototypejs.org/api">Prototype API</a>'
    + Object.toHTML("Hello world!");
    +//-> "Hello world!"
    + Object.toHTML();
    +//-> ""
    + Object.toHTML(null);
    +//-> ""
    + Object.toHTML(undefined);
    +//-> ""
    + Object.toHTML(true);
    +//-> "true"
    + Object.toHTML(false);
    +//-> "false"
    + Object.toHTML(123);
    +//-> "123"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/tojson/index.html b/doc/language/object/tojson/index.html new file mode 100644 index 000000000..159f39b88 --- /dev/null +++ b/doc/language/object/tojson/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.toJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toJSON +

    + + + + +
    +
    +
    +
    +
    +
    Object.toJSON(object) → String
    +
      +
    • + object + (Object) + – The object to be serialized. +
    • +
    + + +

    Returns a JSON string.

    + +

    undefined and function types have no JSON representation. boolean +and null are coerced to strings.

    + +

    For other types, Object.toJSON looks for a toJSON method on object. +If there is one, it is used; otherwise the object is treated like a +generic Object.

    + +

    For more information on Prototype's JSON encoder, hop to our +tutorial.

    + +
    Example
    + +
    var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']};
    +Object.toJSON(data);
    +//-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/toquerystring/index.html b/doc/language/object/toquerystring/index.html new file mode 100644 index 000000000..c8de07e18 --- /dev/null +++ b/doc/language/object/toquerystring/index.html @@ -0,0 +1,181 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.toQueryString + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.toQueryString +

    + + + + +
    +
    +
    +
    +
    +
    Object.toQueryString(object) → String
    +
      +
    • + object + (Object) + – The object whose property/value pairs will be converted. +
    • +
    + + +

    Turns an object into its URL-encoded query string representation.

    + +

    This is a form of serialization, and is mostly useful to provide complex +parameter sets for stuff such as objects in the Ajax namespace (e.g. +Ajax.Request).

    + +

    Undefined-value pairs will be serialized as if empty-valued. Array-valued +pairs will get serialized with one name/value pair per array element. All +values get URI-encoded using JavaScript's native encodeURIComponent +function.

    + +

    The order of pairs in the serialized form is not guaranteed (and mostly +irrelevant anyway) — except for array-based parts, which are serialized +in array order.

    + +
    Examples
    + +
    Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' })
    +// -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a%20demo'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/object/values/index.html b/doc/language/object/values/index.html new file mode 100644 index 000000000..7cc1c80ac --- /dev/null +++ b/doc/language/object/values/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | Object.values + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Object.values +

    + + + + +
    +
    +
    +
    +
    +
    Object.values(object) → Array
    +
      +
    • + object + (Object) + – The object to pull values from. +
    • +
    + + +

    Returns an array of the object's property values.

    + +

    Note that the order of the resulting array is browser-dependent — it +relies on the for...in loop, for which the ECMAScript spec does not +prescribe an enumeration order.

    + +

    Also, remember that while property names are unique, property values +have no such constraint.

    + +
    Examples
    + +
    Object.values();
    +// -> []
    + Object.values({ name: 'Prototype', version: '1.6.1' }).sort();
    +// -> ['1.6.1', 'Prototype']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/objectrange/index.html b/doc/language/objectrange/index.html new file mode 100644 index 000000000..5586ce04d --- /dev/null +++ b/doc/language/objectrange/index.html @@ -0,0 +1,199 @@ + + + + + Prototype v1.7_rc1 API documentation | ObjectRange + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class ObjectRange +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A succession of values.

    + +

    An ObjectRange can model a range of any value that implements a succ +method (which links that value to its "successor").

    + +

    Prototype provides such a method for Number and String, but you +are (of course) welcome to implement useful semantics in your own objects, +in order to enable ranges based on them.

    + +

    ObjectRange mixes in Enumerable, which makes ranges very versatile. +It takes care, however, to override the default code for include, to +achieve better efficiency.

    + +

    While ObjectRange does provide a constructor, the preferred way to obtain +a range is to use the $R utility function, which is strictly equivalent +(only way more concise to use).

    + +

    See $R for more information.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance properties

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/objectrange/new/index.html b/doc/language/objectrange/new/index.html new file mode 100644 index 000000000..1d2a34525 --- /dev/null +++ b/doc/language/objectrange/new/index.html @@ -0,0 +1,146 @@ + + + + + Prototype v1.7_rc1 API documentation | new ObjectRange + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new ObjectRange +

    + + + + +
    +
    +
    +
    +
    +
    new(start, end[, exclusive = false])
    + + +

    Creates a new ObjectRange.

    + +

    The exclusive argument specifies whether end itself is a part of the +range.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/objectrange/prototype/end/index.html b/doc/language/objectrange/prototype/end/index.html new file mode 100644 index 000000000..00beb1af3 --- /dev/null +++ b/doc/language/objectrange/prototype/end/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | ObjectRange#end + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property ObjectRange#end +

    + + + + +
    +
    +
    +
    +
    +
    ObjectRange#end → ?
    + + +

    The upper bounding value of the range.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/objectrange/prototype/include/index.html b/doc/language/objectrange/prototype/include/index.html new file mode 100644 index 000000000..004c5ac4c --- /dev/null +++ b/doc/language/objectrange/prototype/include/index.html @@ -0,0 +1,162 @@ + + + + + Prototype v1.7_rc1 API documentation | ObjectRange#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method ObjectRange#include +

    + + + + +
    +
    +
    +
    +
    +
    ObjectRange#include(value) → Boolean
    + + +

    Determines whether the value is included in the range.

    + +

    This assumes the values in the range have a valid strict weak ordering +(have valid semantics for the < operator). While ObjectRange mixes +in Enumerable, this method overrides the default version of +Enumerable#include, and is much more efficient (it uses a maximum of +two comparisons).

    + +
    Examples
    + +
    $R(1, 10).include(5);
    +// -> true
    + $R('a', 'h').include('x');
    +// -> false
    + $R(1, 10).include(10);
    +// -> true
    + $R(1, 10, true).include(10);
    +// -> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/objectrange/prototype/start/index.html b/doc/language/objectrange/prototype/start/index.html new file mode 100644 index 000000000..c04f787a1 --- /dev/null +++ b/doc/language/objectrange/prototype/start/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | ObjectRange#start + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance property ObjectRange#start +

    + + + + +
    +
    +
    +
    +
    +
    ObjectRange#start → ?
    + + +

    The lower bounding value of the range.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/periodicalexecuter/index.html b/doc/language/periodicalexecuter/index.html new file mode 100644 index 000000000..2cb69893a --- /dev/null +++ b/doc/language/periodicalexecuter/index.html @@ -0,0 +1,183 @@ + + + + + Prototype v1.7_rc1 API documentation | PeriodicalExecuter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class PeriodicalExecuter +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Oversees the calling of a particular function periodically.

    + +

    PeriodicalExecuter shields you from multiple parallel executions of a +callback function, should it take longer than the given interval to +execute.

    + +

    This is especially useful if you use one to interact with the user at +given intervals (e.g. use a prompt or confirm call): this will avoid +multiple message boxes all waiting to be actioned.

    + +
    Example
    + +
    new PeriodicalExecuter(function(pe) {
    +  if (!confirm('Want me to annoy you again later?')) {
    +    pe.stop();
    +  }
    +}, 5);
    +
    +
    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    + +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/periodicalexecuter/new/index.html b/doc/language/periodicalexecuter/new/index.html new file mode 100644 index 000000000..c91d38a36 --- /dev/null +++ b/doc/language/periodicalexecuter/new/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | new PeriodicalExecuter + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new PeriodicalExecuter +

    + + + + +
    +
    +
    +
    +
    +
    new(callback, frequency)
    +
      +
    • + callback + (Function) + – the function to be executed at each interval. +
    • +
    • + frequency + (Number) + – the amount of time, in seconds, to wait in between callbacks. +
    • +
    + + +

    Creates a PeriodicalExecuter.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/periodicalexecuter/prototype/stop/index.html b/doc/language/periodicalexecuter/prototype/stop/index.html new file mode 100644 index 000000000..03848a03a --- /dev/null +++ b/doc/language/periodicalexecuter/prototype/stop/index.html @@ -0,0 +1,160 @@ + + + + + Prototype v1.7_rc1 API documentation | PeriodicalExecuter#stop + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method PeriodicalExecuter#stop +

    + + + + +
    +
    +
    +
    +
    +
    PeriodicalExecuter#stop() → undefined
    + + +

    Stops the periodical executer (there will be no further triggers).

    + +

    Once a PeriodicalExecuter is created, it constitues an infinite loop, +triggering at the given interval until the page unloads. This method lets +you stop it any time you want.

    + +
    Example
    + +

    This will only alert 1, 2 and 3, then the PeriodicalExecuter stops.

    + +
    var count = 0;
    +new PeriodicalExecuter(function(pe) {
    +  if (++count > 3) {
    +    pe.stop();
    +  } else {
    +    alert(count);
    +  }
    +}, 1);
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/browser/index.html b/doc/language/prototype/browser/index.html new file mode 100644 index 000000000..12f8d9c2b --- /dev/null +++ b/doc/language/prototype/browser/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Browser + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Prototype.Browser +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A collection of Boolean values indicating the browser which is +currently in use. Available properties are IE, Opera, WebKit, +MobileSafari and Gecko.

    + +

    Example

    + +
    Prototype.Browser.WebKit;
    +//-> true, when executed in any WebKit-based browser.
    +
    +
    +
    +
    + + + + + + + + + + + +
    + + + +
    + + diff --git a/doc/language/prototype/browserfeatures/elementextensions/index.html b/doc/language/prototype/browserfeatures/elementextensions/index.html new file mode 100644 index 000000000..b566f4910 --- /dev/null +++ b/doc/language/prototype/browserfeatures/elementextensions/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.BrowserFeatures.ElementExtensions + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Prototype.BrowserFeatures.ElementExtensions +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.BrowserFeatures.ElementExtensions → Boolean
    + + +

    Used internally to detect if the browser supports extending html element +prototypes.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/browserfeatures/index.html b/doc/language/prototype/browserfeatures/index.html new file mode 100644 index 000000000..d8b49b9da --- /dev/null +++ b/doc/language/prototype/browserfeatures/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.BrowserFeatures + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Prototype.BrowserFeatures +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A collection of Boolean values indicating the presence of specific +browser features.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class properties

    +
    + +
    + + +
    + + + +
    + + diff --git a/doc/language/prototype/browserfeatures/selectorsapi/index.html b/doc/language/prototype/browserfeatures/selectorsapi/index.html new file mode 100644 index 000000000..45f30eb41 --- /dev/null +++ b/doc/language/prototype/browserfeatures/selectorsapi/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.BrowserFeatures.SelectorsAPI + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Prototype.BrowserFeatures.SelectorsAPI +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.BrowserFeatures.SelectorsAPI → Boolean
    + + +

    Used internally to detect if the browser supports the +NodeSelector API.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/browserfeatures/xpath/index.html b/doc/language/prototype/browserfeatures/xpath/index.html new file mode 100644 index 000000000..ab1d2c14c --- /dev/null +++ b/doc/language/prototype/browserfeatures/xpath/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.BrowserFeatures.XPath + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Prototype.BrowserFeatures.XPath +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.BrowserFeatures.XPath → Boolean
    + + +

    Used internally to detect if the browser supports +DOM Level 3 XPath.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/emptyfunction/index.html b/doc/language/prototype/emptyfunction/index.html new file mode 100644 index 000000000..342645597 --- /dev/null +++ b/doc/language/prototype/emptyfunction/index.html @@ -0,0 +1,153 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.emptyFunction + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.emptyFunction +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.emptyFunction([argument...]) → undefined
    +
      +
    • + argument + (Object) + – Optional arguments +
    • +
    + + +

    The Prototype.emptyFunction does nothing... and returns nothing!

    + +

    It is used thoughout the framework to provide a fallback function in order +to cut down on conditionals. Typically you'll find it as a default value +for optional callback functions.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/index.html b/doc/language/prototype/index.html new file mode 100644 index 000000000..9ae145e96 --- /dev/null +++ b/doc/language/prototype/index.html @@ -0,0 +1,240 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Prototype +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    The Prototype namespace provides fundamental information about the +Prototype library you're using, as well as a central repository for default +iterators or functions.

    + +

    We say "namespace," because the Prototype object is not intended for +instantiation, nor for mixing in other objects. It's really just... a +namespace.

    + +
    Your version of Prototype
    + +

    Your scripts can check against a particular version of Prototype by +examining Prototype.Version, which is a version String (e.g. +"<%= PROTOTYPE_VERSION %>"). The famous +script.aculo.us library does this at load time to +ensure it's being used with a reasonably recent version of Prototype, for +instance.

    + +
    Browser features
    + +

    Prototype also provides a (nascent) repository of +browser feature information, which it then +uses here and there in its source code. The idea is, first, to make +Prototype's source code more readable; and second, to centralize whatever +scripting trickery might be necessary to detect the browser feature, in +order to ease maintenance.

    + +
    Default iterators and functions
    + +

    Numerous methods in Prototype objects (most notably the Enumerable +module) let the user pass in a custom iterator, but make it optional by +defaulting to an "identity function" (an iterator that just returns its +argument, untouched). This is the Prototype.K function, which you'll +see referred to in many places.

    + +

    Many methods also take it easy by protecting themselves against missing +methods here and there, reverting to empty functions when a supposedly +available method is missing. Such a function simply ignores its potential +arguments, and does nothing whatsoever (which is, oddly enough, +blazing fast). The quintessential empty function sits, unsurprisingly, +at Prototype.emptyFunction (note the lowercase first letter).

    +
    +
    + + +
    +
    +

    Namespaces

    +
    +
    + +
      +
    • +

      Prototype.Selector

      + +

      A namespace that acts as a wrapper around +the choosen selector engine (Sizzle by default).

      +
    • +
    • +

      Prototype.Browser

      + +

      A collection of Boolean values indicating the browser which is +currently in use. Available properties are IE, Opera, WebKit, +MobileSafari and Gecko.

      +
    • +
    • +

      Prototype.BrowserFeatures

      + +

      A collection of Boolean values indicating the presence of specific +browser features.

      +
    • +
    +
    +
    + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Class properties

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/prototype/k/index.html b/doc/language/prototype/k/index.html new file mode 100644 index 000000000..f4869386c --- /dev/null +++ b/doc/language/prototype/k/index.html @@ -0,0 +1,165 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.K + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.K +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.K(argument) → argument
    +
      +
    • + argument + (Object) + – Optional argument... +
    • +
    + + +

    Prototype.K is Prototype's very own +identity function, i.e. +it returns its argument untouched.

    + +

    This is used throughout the framework, most notably in the Enumerable +module as a default value for iterators.

    + +
    Examples
    + +
    Prototype.K('hello world!');
    +// -> 'hello world!'
    + Prototype.K(200);
    +// -> 200
    + Prototype.K(Prototype.K);
    +// -> Prototype.K
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/selector/find/index.html b/doc/language/prototype/selector/find/index.html new file mode 100644 index 000000000..28c001a2c --- /dev/null +++ b/doc/language/prototype/selector/find/index.html @@ -0,0 +1,161 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Selector.find + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.Selector.find +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.Selector.find(elements, expression[, index = 0]) → Element
    +
      +
    • + elements + (Enumerable) + – a collection of DOM elements. +
    • +
    • + expression + (String) + – A CSS selector. +
    • +
    • + index + – Numeric index of the match to return, defaults to 0. +
    • +
    + + +

    Filters the given collection of elements with expression and returns the +first matching element (or the indexth matching element if index is +specified).

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/selector/index.html b/doc/language/prototype/selector/index.html new file mode 100644 index 000000000..0e2485233 --- /dev/null +++ b/doc/language/prototype/selector/index.html @@ -0,0 +1,164 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Selector + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Prototype.Selector +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A namespace that acts as a wrapper around +the choosen selector engine (Sizzle by default).

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/prototype/selector/match/index.html b/doc/language/prototype/selector/match/index.html new file mode 100644 index 000000000..da55b9221 --- /dev/null +++ b/doc/language/prototype/selector/match/index.html @@ -0,0 +1,155 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Selector.match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.Selector.match +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.Selector.match(element, expression) → Boolean
    +
      +
    • + element + (Element) + – a DOM element. +
    • +
    • + expression + (String) + – A CSS selector. +
    • +
    + + +

    Tests whether element matches the CSS selector.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/selector/select/index.html b/doc/language/prototype/selector/select/index.html new file mode 100644 index 000000000..29e561974 --- /dev/null +++ b/doc/language/prototype/selector/select/index.html @@ -0,0 +1,156 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Selector.select + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method Prototype.Selector.select +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.Selector.select(expression[, root = document]) → [Element…]
    +
      +
    • + expression + (String) + – A CSS selector. +
    • +
    • + root + (Element | document) + – A "scope" to search within. All results will be descendants of this node. +
    • +
    + + +

    Searches root for elements that match the provided CSS selector and returns an +array of extended Element objects.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/prototype/version/index.html b/doc/language/prototype/version/index.html new file mode 100644 index 000000000..8e2d79da9 --- /dev/null +++ b/doc/language/prototype/version/index.html @@ -0,0 +1,143 @@ + + + + + Prototype v1.7_rc1 API documentation | Prototype.Version + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class property Prototype.Version +

    + + + + +
    +
    +
    +
    +
    +
    Prototype.Version → String
    + + +

    The version of the Prototype library you are using (e.g. +"<%= PROTOTYPE_VERSION %>").

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/regexp/escape/index.html b/doc/language/regexp/escape/index.html new file mode 100644 index 000000000..d6e95cfb7 --- /dev/null +++ b/doc/language/regexp/escape/index.html @@ -0,0 +1,151 @@ + + + + + Prototype v1.7_rc1 API documentation | RegExp.escape + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method RegExp.escape +

    + + + + +
    +
    +
    +
    +
    +
    RegExp.escape(str) → String
    +
      +
    • + str + (String) + – A string intended to be used in a RegExp constructor. +
    • +
    + + +

    Escapes any characters in the string that have special meaning in a +regular expression.

    + +

    Use before passing a string into the RegExp constructor.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/regexp/index.html b/doc/language/regexp/index.html new file mode 100644 index 000000000..969e1907a --- /dev/null +++ b/doc/language/regexp/index.html @@ -0,0 +1,168 @@ + + + + + Prototype v1.7_rc1 API documentation | RegExp + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class RegExp +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in RegExp object.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/regexp/prototype/match/index.html b/doc/language/regexp/prototype/match/index.html new file mode 100644 index 000000000..56a20f005 --- /dev/null +++ b/doc/language/regexp/prototype/match/index.html @@ -0,0 +1,141 @@ + + + + + Prototype v1.7_rc1 API documentation | RegExp#match + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method RegExp#match +

    + + + + +
    +
    +
    +
    +
    +
    RegExp#match(str) → Boolean
    + + +

    Return true if string matches the regular expression, false otherwise.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/index.html b/doc/language/string/index.html new file mode 100644 index 000000000..036b40349 --- /dev/null +++ b/doc/language/string/index.html @@ -0,0 +1,261 @@ + + + + + Prototype v1.7_rc1 API documentation | String + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class String +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    Extensions to the built-in String class.

    + +

    Prototype enhances the String object with a series of useful methods for +ranging from the trivial to the complex. Tired of stripping trailing +whitespace? Try String#strip. Want to replace replace? Have a look at +String#sub and String#gsub. Need to parse a query string? We have +what you need.

    +
    +
    + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + + + +
    + + + +
    + + diff --git a/doc/language/string/interpret/index.html b/doc/language/string/interpret/index.html new file mode 100644 index 000000000..0840f2281 --- /dev/null +++ b/doc/language/string/interpret/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | String.interpret + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class method String.interpret +

    + + + + +
    +
    +
    +
    +
    +
    String.interpret(value) → String
    + + +

    Coerces value into a string. Returns an empty string for null.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/blank/index.html b/doc/language/string/prototype/blank/index.html new file mode 100644 index 000000000..ca686a49b --- /dev/null +++ b/doc/language/string/prototype/blank/index.html @@ -0,0 +1,182 @@ + + + + + Prototype v1.7_rc1 API documentation | String#blank + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#blank +

    + + + + +
    +
    +
    +
    +
    +
    String#blank() → Boolean
    + + +

    Check if the string is "blank" — either empty (length of 0) or +containing only whitespace.

    + +
    Example
    + +
    ''.blank();
    +//-> true
    + '  '.blank();
    +//-> true
    + ' a '.blank();
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/camelize/index.html b/doc/language/string/prototype/camelize/index.html new file mode 100644 index 000000000..fd61d74ab --- /dev/null +++ b/doc/language/string/prototype/camelize/index.html @@ -0,0 +1,183 @@ + + + + + Prototype v1.7_rc1 API documentation | String#camelize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#camelize +

    + + + + +
    +
    +
    +
    +
    +
    String#camelize() → String
    + + +

    Converts a string separated by dashes into a camelCase equivalent. For +instance, 'foo-bar' would be converted to 'fooBar'.

    + +

    Prototype uses this internally for translating CSS properties into their +DOM style property equivalents.

    + +
    Examples
    + +
    'background-color'.camelize();
    +// -> 'backgroundColor'
    + '-moz-binding'.camelize();
    +// -> 'MozBinding'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/capitalize/index.html b/doc/language/string/prototype/capitalize/index.html new file mode 100644 index 000000000..35aa28c83 --- /dev/null +++ b/doc/language/string/prototype/capitalize/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | String#capitalize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#capitalize +

    + + + + +
    +
    +
    +
    +
    +
    String#capitalize() → String
    + + +

    Capitalizes the first letter of a string and downcases all the others.

    + +
    Examples
    + +
    'hello'.capitalize();
    +// -> 'Hello'
    + 'HELLO WORLD!'.capitalize();
    +// -> 'Hello world!'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/dasherize/index.html b/doc/language/string/prototype/dasherize/index.html new file mode 100644 index 000000000..a56a10d84 --- /dev/null +++ b/doc/language/string/prototype/dasherize/index.html @@ -0,0 +1,187 @@ + + + + + Prototype v1.7_rc1 API documentation | String#dasherize + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#dasherize +

    + + + + +
    +
    +
    +
    +
    +
    String#dasherize() → String
    + + +

    Replaces every instance of the underscore character "_" by a dash "-".

    + +
    Example
    + +
    'border_bottom_width'.dasherize();
    +// -> 'border-bottom-width'
    +
    +
    + +
    Note
    + +

    Used in conjunction with String#underscore, String#dasherize +converts a DOM style into its CSS equivalent.

    + +
    'borderBottomWidth'.underscore().dasherize();
    +// -> 'border-bottom-width'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/empty/index.html b/doc/language/string/prototype/empty/index.html new file mode 100644 index 000000000..6a46a82b6 --- /dev/null +++ b/doc/language/string/prototype/empty/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | String#empty + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#empty +

    + + + + +
    +
    +
    +
    +
    +
    String#empty() → Boolean
    + + +

    Checks if the string is empty.

    + +
    Example
    + +
    ''.empty();
    +//-> true
    + '  '.empty();
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/endswith/index.html b/doc/language/string/prototype/endswith/index.html new file mode 100644 index 000000000..59865e2a7 --- /dev/null +++ b/doc/language/string/prototype/endswith/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#endsWith + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#endsWith +

    + + + + +
    +
    +
    +
    +
    +
    String#endsWith(substring) → Boolean
    + + +

    Checks if the string ends with substring.

    + +
    Example
    + +
    'slaughter'.endsWith('laughter')
    +// -> true
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/escapehtml/index.html b/doc/language/string/prototype/escapehtml/index.html new file mode 100644 index 000000000..43dc6a56c --- /dev/null +++ b/doc/language/string/prototype/escapehtml/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#escapeHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#escapeHTML +

    + + + + +
    +
    +
    +
    +
    +
    String#escapeHTML() → String
    + + +

    Converts HTML special characters to their entity equivalents.

    + +
    Example
    + +
    '<div class="article">This is an article</div>'.escapeHTML();
    +// -> "&lt;div class="article"&gt;This is an article&lt;/div&gt;"
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/evaljson/index.html b/doc/language/string/prototype/evaljson/index.html new file mode 100644 index 000000000..5f5d3cc41 --- /dev/null +++ b/doc/language/string/prototype/evaljson/index.html @@ -0,0 +1,201 @@ + + + + + Prototype v1.7_rc1 API documentation | String#evalJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#evalJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#evalJSON([sanitize = false]) → object
    + + +

    Evaluates the JSON in the string and returns the resulting object.

    + +

    If the optional sanitize parameter is set to true, the string is +checked for possible malicious attempts; if one is detected, eval +is not called.

    + +
    Warning
    + +

    If the JSON string is not well formated or if a malicious attempt is +detected a SyntaxError is thrown.

    + +
    Examples
    + +
    var person = '{ "name": "Violet", "occupation": "character" }'.evalJSON();
    +person.name;
    +//-> "Violet"
    + person = 'grabUserPassword()'.evalJSON(true);
    +//-> SyntaxError: Badly formed JSON string: 'grabUserPassword()'
    + person = '/*-secure-\n{"name": "Violet", "occupation": "character"}\n*\/'.evalJSON()
    +person.name;
    +//-> "Violet"
    +
    +
    + +
    Note
    + +

    Always set the sanitize parameter to true for data coming from +externals sources to prevent XSS attacks.

    + +

    As String#evalJSON internally calls String#unfilterJSON, optional +security comment delimiters (defined in Prototype.JSONFilter) are +automatically removed.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/evalscripts/index.html b/doc/language/string/prototype/evalscripts/index.html new file mode 100644 index 000000000..2c6f47d08 --- /dev/null +++ b/doc/language/string/prototype/evalscripts/index.html @@ -0,0 +1,220 @@ + + + + + Prototype v1.7_rc1 API documentation | String#evalScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#evalScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#evalScripts() → Array
    + + +

    Evaluates the content of any inline <script> block present in the string. +Returns an array containing the value returned by each script. +<script> blocks referencing external files will be treated as though +they were empty (the result for that position in the array will be undefined); +external files are not loaded and processed by String#evalScripts.

    + +
    Examples
    + +
    'lorem... <script>2 + 2</script>'.evalScripts();
    +// -> [4]
    + '<script>2 + 2<script><script>alert("hello world!")</script>'.evalScripts();
    +// -> [4, undefined] (and displays 'hello world!' in the alert dialog)
    +
    +
    + +
    About evalScripts, vars, and defining functions
    + +

    String#evalScripts evaluates script blocks, but this does not mean +they are evaluated in the global scope. They aren't, they're evaluated in +the scope of the String#evalScripts method. This has important +ramifications for your scripts:

    + +
      +
    • Anything in your script declared with the var keyword will be +discarded momentarily after evaluation, and will be invisible to any +other scope.
    • +
    • If any <script> blocks define functions, they will need to be +assigned to properties of the window object.
    • +
    + +

    For example, this won't work:

    + +
    // This kind of script won't work if processed by evalScripts:
    +function coolFunc() {
    +  // Amazing stuff!
    +}
    +
    +
    + +

    Instead, use the following syntax:

    + +
    // This kind of script WILL work if processed by evalScripts:
    +window.coolFunc = function() {
    +  // Amazing stuff!
    +}
    +
    +
    + +

    (You can leave off the window. part of that, but it's bad form.) +Evaluates the content of any script block present in the string. Returns +an array containing the value returned by each script.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/extractscripts/index.html b/doc/language/string/prototype/extractscripts/index.html new file mode 100644 index 000000000..2b2791c99 --- /dev/null +++ b/doc/language/string/prototype/extractscripts/index.html @@ -0,0 +1,197 @@ + + + + + Prototype v1.7_rc1 API documentation | String#extractScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#extractScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#extractScripts() → Array
    + + +

    Extracts the content of any <script> blocks present in the string and +returns them as an array of strings.

    + +

    This method is used internally by String#evalScripts. It does not +evaluate the scripts (use String#evalScripts to do that), but can be +usefull if you need to evaluate the scripts at a later date.

    + +
    Examples
    + +
    'lorem... <script>2 + 2</script>'.extractScripts();
    +// -> ['2 + 2']
    + '<script>2 + 2</script><script>alert("hello world!")</script>'.extractScripts();
    +// -> ['2 + 2', 'alert("hello world!")']
    +
    +
    + +
    Notes
    + +

    To evaluate the scripts later on, you can use the following:

    + +
    var myScripts = '<script>2 + 2</script><script>alert("hello world!")</script>'.extractScripts();
    +// -> ['2 + 2', 'alert("hello world!")']
    + var myReturnedValues = myScripts.map(function(script) {
    +  return eval(script);
    +});
    +// -> [4, undefined] (and displays 'hello world!' in the alert dialog)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/gsub/index.html b/doc/language/string/prototype/gsub/index.html new file mode 100644 index 000000000..1a7e01eb1 --- /dev/null +++ b/doc/language/string/prototype/gsub/index.html @@ -0,0 +1,215 @@ + + + + + Prototype v1.7_rc1 API documentation | String#gsub + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#gsub +

    + + + + +
    +
    +
    +
    +
    +
    String#gsub(pattern, replacement) → String
    + + +

    Returns the string with every occurence of a given pattern replaced by either a +regular string, the returned value of a function or a Template string. +The pattern can be a string or a regular expression.

    + +

    If its second argument is a string String#gsub works just like the native JavaScript +method replace() set to global match.

    + +
    var mouseEvents = 'click dblclick mousedown mouseup mouseover mousemove mouseout';
    + mouseEvents.gsub(' ', ', ');
    +// -> 'click, dblclick, mousedown, mouseup, mouseover, mousemove, mouseout'
    + mouseEvents.gsub(/\s+/, ', ');
    +// -> 'click, dblclick, mousedown, mouseup, mouseover, mousemove, mouseout'
    +
    +
    + +

    If you pass it a function, it will be invoked for every occurrence of the pattern +with the match of the current pattern as its unique argument. Note that this argument +is the returned value of the match() method called on the current pattern. It is +in the form of an array where the first element is the entire match and every subsequent +one corresponds to a parenthesis group in the regex.

    + +
    mouseEvents.gsub(/\w+/, function(match){ return 'on' + match[0].capitalize() });
    +// -> 'onClick onDblclick onMousedown onMouseup onMouseover onMousemove onMouseout'
    + var markdown = '![a pear](/img/pear.jpg) ![an orange](/img/orange.jpg)';
    + markdown.gsub(/!\[(.*?)\]\((.*?)\)/, function(match) {
    +  return '<img alt="' + match[1] + '" src="' + match[2] + '" />';
    +});
    +// -> '<img alt="a pear" src="/img/pear.jpg" /> <img alt="an orange" src="/img/orange.jpg" />'
    +
    +
    + +

    Lastly, you can pass String#gsub a Template string in which you can also access +the returned value of the match() method using the ruby inspired notation: #{0} +for the first element of the array, #{1} for the second one, and so on. +So our last example could be easily re-written as:

    + +
    markdown.gsub(/!\[(.*?)\]\((.*?)\)/, '<img alt="#{1}" src="#{2}" />');
    +// -> '<img alt="a pear" src="/img/pear.jpg" /> <img alt="an orange" src="/img/orange.jpg" />'
    +
    +
    + +

    If you need an equivalent to String#gsub but without global match set on, try String#sub.

    + +
    Note
    + +

    Do not use the "g" flag on the regex as this will create an infinite loop.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/include/index.html b/doc/language/string/prototype/include/index.html new file mode 100644 index 000000000..db7b6cfee --- /dev/null +++ b/doc/language/string/prototype/include/index.html @@ -0,0 +1,179 @@ + + + + + Prototype v1.7_rc1 API documentation | String#include + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#include +

    + + + + +
    +
    +
    +
    +
    +
    String#include(substring) → Boolean
    + + +

    Checks if the string contains substring.

    + +
    Example
    + +
    'Prototype framework'.include('frame');
    +//-> true
    +'Prototype framework'.include('frameset');
    +//-> false
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/inspect/index.html b/doc/language/string/prototype/inspect/index.html new file mode 100644 index 000000000..cf2eec702 --- /dev/null +++ b/doc/language/string/prototype/inspect/index.html @@ -0,0 +1,184 @@ + + + + + Prototype v1.7_rc1 API documentation | String#inspect + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#inspect +

    + + + + +
    +
    +
    +
    +
    +
    String#inspect([useDoubleQuotes = false]) → String
    + + +

    Returns a debug-oriented version of the string (i.e. wrapped in single or +double quotes, with backslashes and quotes escaped).

    + +

    For more information on inspect methods, see Object.inspect.

    + +

    Examples

    + +
    'I\'m so happy.'.inspect();
    +// -> '\'I\\\'m so happy.\''
    +// (displayed as 'I\'m so happy.' in an alert dialog or the console)
    + 'I\'m so happy.'.inspect(true);
    +// -> '"I'm so happy."'
    +// (displayed as "I'm so happy." in an alert dialog or the console)
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/interpolate/index.html b/doc/language/string/prototype/interpolate/index.html new file mode 100644 index 000000000..53c438d45 --- /dev/null +++ b/doc/language/string/prototype/interpolate/index.html @@ -0,0 +1,171 @@ + + + + + Prototype v1.7_rc1 API documentation | String#interpolate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#interpolate +

    + + + + +
    +
    +
    +
    +
    +
    String#interpolate(object[, pattern]) → String
    + + +

    Treats the string as a Template and fills it with object's +properties.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/isjson/index.html b/doc/language/string/prototype/isjson/index.html new file mode 100644 index 000000000..5c228582e --- /dev/null +++ b/doc/language/string/prototype/isjson/index.html @@ -0,0 +1,184 @@ + + + + + Prototype v1.7_rc1 API documentation | String#isJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#isJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#isJSON() → Boolean
    + + +

    Check if the string is valid JSON by the use of regular expressions. +This security method is called internally.

    + +
    Examples
    + +
    "something".isJSON();
    +// -> false
    +"\"something\"".isJSON();
    +// -> true
    +"{ foo: 42 }".isJSON();
    +// -> false
    +"{ \"foo\": 42 }".isJSON();
    +// -> true
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/parsequery/index.html b/doc/language/string/prototype/parsequery/index.html new file mode 100644 index 000000000..effae03d5 --- /dev/null +++ b/doc/language/string/prototype/parsequery/index.html @@ -0,0 +1,170 @@ + + + + + Prototype v1.7_rc1 API documentation | String#parseQuery + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#parseQuery +

    + + + + +
    +
    +
    +
    +
    +
    String#parseQuery([separator = '&']) → Object
    + + + + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/scan/index.html b/doc/language/string/prototype/scan/index.html new file mode 100644 index 000000000..ddc6f4b82 --- /dev/null +++ b/doc/language/string/prototype/scan/index.html @@ -0,0 +1,201 @@ + + + + + Prototype v1.7_rc1 API documentation | String#scan + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#scan +

    + + + + +
    +
    +
    +
    +
    +
    String#scan(pattern, iterator) → String
    + + +

    Allows iterating over every occurrence of the given pattern (which can be a +string or a regular expression). +Returns the original string.

    + +

    Internally just calls String#gsub passing it pattern and iterator as arguments.

    + +
    Examples
    + +
    'apple, pear & orange'.scan(/\w+/, alert);
    +// -> 'apple pear orange' (and displays 'apple', 'pear' and 'orange' in three successive alert dialogs)
    +
    +
    + +

    Can be used to populate an array:

    + +
    var fruits = [];
    +'apple, pear & orange'.scan(/\w+/, function(match) { fruits.push(match[0]) });
    +fruits.inspect()
    +// -> ['apple', 'pear', 'orange']
    +
    +
    + +

    or even to work on the DOM:

    + +
    'failure-message, success-message & spinner'.scan(/(\w|-)+/, Element.toggle)
    +// -> 'failure-message, success-message & spinner' (and toggles the visibility of each DOM element)
    +
    +
    + +
    Note
    + +

    Do not use the "g" flag on the regex as this will create an infinite loop.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/startswith/index.html b/doc/language/string/prototype/startswith/index.html new file mode 100644 index 000000000..9a697fa1b --- /dev/null +++ b/doc/language/string/prototype/startswith/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#startsWith + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#startsWith +

    + + + + +
    +
    +
    +
    +
    +
    String#startsWith(substring) → Boolean
    + + +

    Checks if the string starts with substring.

    + +
    Example
    + +
    'Prototype JavaScript'.startsWith('Pro');
    +//-> true
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/strip/index.html b/doc/language/string/prototype/strip/index.html new file mode 100644 index 000000000..bf0064984 --- /dev/null +++ b/doc/language/string/prototype/strip/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#strip + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#strip +

    + + + + +
    +
    +
    +
    +
    +
    String#strip() → String
    + + +

    Strips all leading and trailing whitespace from a string.

    + +
    Example
    + +
    '    hello world!    '.strip();
    +// -> 'hello world!'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/stripscripts/index.html b/doc/language/string/prototype/stripscripts/index.html new file mode 100644 index 000000000..52d144a42 --- /dev/null +++ b/doc/language/string/prototype/stripscripts/index.html @@ -0,0 +1,184 @@ + + + + + Prototype v1.7_rc1 API documentation | String#stripScripts + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#stripScripts +

    + + + + +
    +
    +
    +
    +
    +
    String#stripScripts() → String
    + + +

    Strips a string of things that look like an HTML script blocks.

    + +
    Example
    + +
    "<p>This is a test.<script>alert("Look, a test!");</script>End of test</p>".stripScripts();
    +// => "<p>This is a test.End of test</p>"
    +
    +
    + +
    Caveat User
    + +

    Note that the processing String#stripScripts does is good enough for +most purposes, but you cannot rely on it for security purposes. If you're +processing end-user-supplied content, String#stripScripts is probably +not sufficiently robust to prevent hack attacks.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/striptags/index.html b/doc/language/string/prototype/striptags/index.html new file mode 100644 index 000000000..593e131fc --- /dev/null +++ b/doc/language/string/prototype/striptags/index.html @@ -0,0 +1,198 @@ + + + + + Prototype v1.7_rc1 API documentation | String#stripTags + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#stripTags +

    + + + + +
    +
    +
    +
    +
    +
    String#stripTags() → String
    + + +

    Strips a string of any HTML tags.

    + +

    Note that String#stripTags will only strip HTML 4.01 tags — like +div, span, and abbr. It will not strip namespace-prefixed tags +such as h:table or xsl:template.

    + +

    Watch out for <script> tags in your string, as String#stripTags will +not remove their content. Use String#stripScripts to do so.

    + +
    Caveat User
    + +

    Note that the processing String#stripTags does is good enough for most +purposes, but you cannot rely on it for security purposes. If you're +processing end-user-supplied content, String#stripTags is not +sufficiently robust to ensure that the content is completely devoid of +HTML tags in the case of a user intentionally trying to circumvent tag +restrictions. But then, you'll be running them through +String#escapeHTML anyway, won't you?

    + +
    Examples
    + +
    'a <a href="#">link</a>'.stripTags();
    + // -> 'a link'
    + 'a <a href="#">link</a><script>alert("hello world!");</script>'.stripTags();
    +// -> 'a linkalert("hello world!");'
    + 'a <a href="#">link</a><script>alert("hello world!");</script>'.stripScripts().stripTags();
    +// -> 'a link'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/sub/index.html b/doc/language/string/prototype/sub/index.html new file mode 100644 index 000000000..a826bd9e5 --- /dev/null +++ b/doc/language/string/prototype/sub/index.html @@ -0,0 +1,204 @@ + + + + + Prototype v1.7_rc1 API documentation | String#sub + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#sub +

    + + + + +
    +
    +
    +
    +
    +
    String#sub(pattern, replacement[, count = 1]) → String
    + + +

    Returns a string with the first count occurrences of pattern replaced by either +a regular string, the returned value of a function or a Template string. +pattern can be a string or a regular expression.

    + +

    Unlike String#gsub, String#sub takes a third optional parameter which specifies +the number of occurrences of the pattern which will be replaced. +If not specified, it will default to 1.

    + +

    Apart from that, String#sub works just like String#gsub. +Please refer to it for a complete explanation.

    + +
    Examples
    + +
    var fruits = 'apple pear orange';
    + fruits.sub(' ', ', ');
    +// -> 'apple, pear orange'
    + fruits.sub(' ', ', ', 1);
    +// -> 'apple, pear orange'
    + fruits.sub(' ', ', ', 2);
    +// -> 'apple, pear, orange'
    + fruits.sub(/\w+/, function(match){ return match[0].capitalize() + ',' }, 2);
    +// -> 'Apple, Pear, orange'
    + var markdown = '![a pear](/img/pear.jpg) ![an orange](/img/orange.jpg)';
    + markdown.sub(/!\[(.*?)\]\((.*?)\)/, function(match) {
    +  return '<img alt="' + match[1] + '" src="' + match[2] + '" />';
    +});
    +// -> '<img alt="a pear" src="/img/pear.jpg" /> ![an orange](/img/orange.jpg)'
    + markdown.sub(/!\[(.*?)\]\((.*?)\)/, '<img alt="#{1}" src="#{2}" />');
    +// -> '<img alt="a pear" src="/img/pear.jpg" /> ![an orange](/img/orange.jpg)'
    +
    +
    + +
    Note
    + +

    Do not use the "g" flag on the regex as this will create an infinite loop.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/succ/index.html b/doc/language/string/prototype/succ/index.html new file mode 100644 index 000000000..aa36de5ec --- /dev/null +++ b/doc/language/string/prototype/succ/index.html @@ -0,0 +1,182 @@ + + + + + Prototype v1.7_rc1 API documentation | String#succ + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#succ +

    + + + + +
    +
    +
    +
    +
    +
    String#succ() → String
    + + +

    Used internally by ObjectRange.

    + +

    Converts the last character of the string to the following character in +the Unicode alphabet.

    + +
    Examples
    + +
    'a'.succ();
    +// -> 'b'
    + 'aaaa'.succ();
    +// -> 'aaab'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/times/index.html b/doc/language/string/prototype/times/index.html new file mode 100644 index 000000000..d3f461645 --- /dev/null +++ b/doc/language/string/prototype/times/index.html @@ -0,0 +1,177 @@ + + + + + Prototype v1.7_rc1 API documentation | String#times + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#times +

    + + + + +
    +
    +
    +
    +
    +
    String#times(count) → String
    + + +

    Concatenates the string count times.

    + +
    Example
    + +
    "echo ".times(3);
    +// -> "echo echo echo "
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/toarray/index.html b/doc/language/string/prototype/toarray/index.html new file mode 100644 index 000000000..bbb47c0fc --- /dev/null +++ b/doc/language/string/prototype/toarray/index.html @@ -0,0 +1,180 @@ + + + + + Prototype v1.7_rc1 API documentation | String#toArray + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#toArray +

    + + + + +
    +
    +
    +
    +
    +
    String#toArray() → Array
    + + +

    Splits the string character-by-character and returns an array with +the result.

    + +
    Examples
    + +
    'a'.toArray();
    +// -> ['a']
    + 'hello world!'.toArray();
    +// -> ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!']
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/toqueryparams/index.html b/doc/language/string/prototype/toqueryparams/index.html new file mode 100644 index 000000000..e3d499096 --- /dev/null +++ b/doc/language/string/prototype/toqueryparams/index.html @@ -0,0 +1,202 @@ + + + + + Prototype v1.7_rc1 API documentation | String#toQueryParams + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#toQueryParams +

    + + + + +
    +
    +
    +
    +
    +
    String#toQueryParams([separator = '&']) → Object
    + + +

    Parses a URI-like query string and returns an object composed of +parameter/value pairs.

    + +

    This method is realy targeted at parsing query strings (hence the default +value of"&" for the separator argument).

    + +

    For this reason, it does not consider anything that is either before a +question mark (which signals the beginning of a query string) or beyond +the hash symbol ("#"), and runs decodeURIComponent() on each +parameter/value pair.

    + +

    String#toQueryParams also aggregates the values of identical keys into +an array of values.

    + +

    Note that parameters which do not have a specified value will be set to +undefined.

    + +
    Examples
    + +
    'section=blog&id=45'.toQueryParams();
    +// -> {section: 'blog', id: '45'}
    + 'section=blog;id=45'.toQueryParams();
    +// -> {section: 'blog', id: '45'}
    + 'http://www.example.com?section=blog&id=45#comments'.toQueryParams();
    +// -> {section: 'blog', id: '45'}
    + 'section=blog&tag=javascript&tag=prototype&tag=doc'.toQueryParams();
    +// -> {section: 'blog', tag: ['javascript', 'prototype', 'doc']}
    + 'tag=ruby%20on%20rails'.toQueryParams();
    +// -> {tag: 'ruby on rails'}
    + 'id=45&raw'.toQueryParams();
    +// -> {id: '45', raw: undefined}
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/truncate/index.html b/doc/language/string/prototype/truncate/index.html new file mode 100644 index 000000000..94b8d4e87 --- /dev/null +++ b/doc/language/string/prototype/truncate/index.html @@ -0,0 +1,184 @@ + + + + + Prototype v1.7_rc1 API documentation | String#truncate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#truncate +

    + + + + +
    +
    +
    +
    +
    +
    String#truncate([length = 30[, suffix = '...']]) → String
    + + +

    Truncates a string to given length and appends suffix to it (indicating +that it is only an excerpt).

    + +
    Examples
    + +
    'A random sentence whose length exceeds 30 characters.'.truncate();
    +// -> 'A random sentence whose len...'
    + 'Some random text'.truncate();
    +// -> 'Some random text.'
    + 'Some random text'.truncate(10);
    +// -> 'Some ra...'
    + 'Some random text'.truncate(10, ' [...]');
    +// -> 'Some [...]'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/underscore/index.html b/doc/language/string/prototype/underscore/index.html new file mode 100644 index 000000000..0d53f00d9 --- /dev/null +++ b/doc/language/string/prototype/underscore/index.html @@ -0,0 +1,188 @@ + + + + + Prototype v1.7_rc1 API documentation | String#underscore + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#underscore +

    + + + + +
    +
    +
    +
    +
    +
    String#underscore() → String
    + + +

    Converts a camelized string into a series of words separated by an +underscore (_).

    + +
    Example
    + +
    'borderBottomWidth'.underscore();
    +// -> 'border_bottom_width'
    +
    +
    + +
    Note
    + +

    Used in conjunction with String#dasherize, String#underscore +converts a DOM style into its CSS equivalent.

    + +
    'borderBottomWidth'.underscore().dasherize();
    +// -> 'border-bottom-width'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/unescapehtml/index.html b/doc/language/string/prototype/unescapehtml/index.html new file mode 100644 index 000000000..d82b2cda1 --- /dev/null +++ b/doc/language/string/prototype/unescapehtml/index.html @@ -0,0 +1,180 @@ + + + + + Prototype v1.7_rc1 API documentation | String#unescapeHTML + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#unescapeHTML +

    + + + + +
    +
    +
    +
    +
    +
    String#unescapeHTML() → String
    + + +

    Strips tags and converts the entity forms of special HTML characters +to their normal form.

    + +
    Examples
    + +
    'x &gt; 10'.unescapeHTML()
    +// -> 'x > 10'
    + '<h1>Pride &amp; Prejudice</h1>;'.unescapeHTML()
    +// -> '<h1>Pride & Prejudice</h1>'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/string/prototype/unfilterjson/index.html b/doc/language/string/prototype/unfilterjson/index.html new file mode 100644 index 000000000..52fb959de --- /dev/null +++ b/doc/language/string/prototype/unfilterjson/index.html @@ -0,0 +1,178 @@ + + + + + Prototype v1.7_rc1 API documentation | String#unfilterJSON + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method String#unfilterJSON +

    + + + + +
    +
    +
    +
    +
    +
    String#unfilterJSON([filter = Prototype.JSONFilter]) → String
    + + +

    Strips comment delimiters around Ajax JSON or JavaScript responses. +This security method is called internally.

    + +
    Example
    + +
    '/*-secure-\n{"name": "Violet", "occupation": "character", "age": 25}\n*\/'.unfilterJSON()
    +// -> '{"name": "Violet", "occupation": "character", "age": 25}'
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/template/index.html b/doc/language/template/index.html new file mode 100644 index 000000000..1b4dd48d3 --- /dev/null +++ b/doc/language/template/index.html @@ -0,0 +1,269 @@ + + + + + Prototype v1.7_rc1 API documentation | Template + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + class Template +

    + + + + +
    +
    +

    Description

    +
    +
    + +

    A class for sophisticated string interpolation.

    + +

    Any time you have a group of similar objects and you need to produce +formatted output for these objects, maybe inside a loop, you typically +resort to concatenating string literals with the object's fields:

    + +
    "The TV show " + title + " was created by " + author + ".";
    +
    +
    + +

    There's nothing wrong with this approach, except that it is hard to +visualize the output immediately just by glancing at the concatenation +expression. The Template class provides a much nicer and clearer way of +achieving this formatting.

    + +
    Straightforward templates
    + +

    The Template class uses a basic formatting syntax, similar to what is +used in Ruby. The templates are created from strings that have embedded +symbols in the form (e.g., #{fieldName}) that will be replaced by +actual values when the template is applied (evaluated) to an object.

    + +
    // the template (our formatting expression)
    +var myTemplate = new Template(
    + 'The TV show #{title} was created by #{author}.');
    + // our data to be formatted by the template
    +var show = {
    +  title: 'The Simpsons',
    +  author: 'Matt Groening',
    +  network: 'FOX'
    +};
    + // let's format our data
    +myTemplate.evaluate(show);
    +// -> "The TV show The Simpsons was created by Matt Groening."
    +
    +
    + +
    Templates are meant to be reused
    + +

    As the example illustrates, Template objects are not tied to specific +data. The data is bound to the template only during the evaluation of the +template, without affecting the template itself. The next example shows the +same template being used with a handful of distinct objects.

    + +
    // creating a few similar objects
    +var conversion1 = { from: 'meters', to: 'feet', factor: 3.28 };
    +var conversion2 = { from: 'kilojoules', to: 'BTUs', factor: 0.9478 };
    +var conversion3 = { from: 'megabytes', to: 'gigabytes', factor: 1024 };
    + // the template
    +var templ = new Template(
    + 'Multiply by #{factor} to convert from #{from} to #{to}.');
    + // let's format each object
    +[conversion1, conversion2, conversion3].each( function(conv){
    +    templ.evaluate(conv);
    +});
    +// -> Multiply by 3.28 to convert from meters to feet.
    +// -> Multiply by 0.9478 to convert from kilojoules to BTUs.
    +// -> Multiply by 1024 to convert from megabytes to gigabytes.
    +
    +
    + +
    Escape sequence
    + +

    There's always the chance that one day you'll need to have a literal in your +template that looks like a symbol, but is not supposed to be replaced. For +these situations there's an escape character: the backslash (\).

    + +
    // NOTE: you're seeing two backslashes here because the backslash
    +// is also an escape character in JavaScript strings, so a literal
    +// backslash is represented by two backslashes.
    +var t = new Template(
    + 'in #{lang} we also use the \\#{variable} syntax for templates.');
    +var data = { lang:'Ruby', variable: '(not used)' };
    +t.evaluate(data);
    +// -> in Ruby we also use the #{variable} syntax for templates.
    +
    +
    + +
    Custom syntaxes
    + +

    The default syntax of the template strings will probably be enough for most +scenarios. In the rare occasion where the default Ruby-like syntax is +inadequate, there's a provision for customization. Template's +constructor accepts an optional second argument that is a regular expression +object to match the replaceable symbols in the template string. Let's put +together a template that uses a syntax similar to the now ubiquitous {{ }} +constructs:

    + +
    // matches symbols like '{{ field }}'
    +var syntax = /(^|.|\r|\n)(\{{\s*(\w+)\s*}})/;
    + var t = new Template(
    + '<div>Name: <b>{{ name }}</b>, Age: <b>{{ age }}</b></div>',
    + syntax);
    +t.evaluate( {name: 'John Smith', age: 26} );
    +// -> <div>Name: <b>John Smith</b>, Age: <b>26</b></div>
    +
    +
    + +

    There are important constraints to any custom syntax. Any syntax must +provide at least three groupings in the regular expression. The first +grouping is to capture what comes before the symbol, to detect the backslash +escape character (no, you cannot use a different character). The second +grouping captures the entire symbol and will be completely replaced upon +evaluation. Lastly, the third required grouping captures the name of the +field inside the symbol.

    +
    +
    + + + + + + + + +
    +
    +

    Constructor

    +
    +
    + +

    new Template

    +
    +
    + + + +
    +
    +

    Instance methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/template/new/index.html b/doc/language/template/new/index.html new file mode 100644 index 000000000..4d3d4fc28 --- /dev/null +++ b/doc/language/template/new/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | new Template + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + constructor new Template +

    + + + + +
    +
    +
    +
    +
    +
    new(template[, pattern = Template.Pattern])
    + + +

    Creates a Template object.

    + +

    The optional pattern argument expects a RegExp that defines a custom +syntax for the replaceable symbols in template.

    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/template/prototype/evaluate/index.html b/doc/language/template/prototype/evaluate/index.html new file mode 100644 index 000000000..960efc545 --- /dev/null +++ b/doc/language/template/prototype/evaluate/index.html @@ -0,0 +1,157 @@ + + + + + Prototype v1.7_rc1 API documentation | Template#evaluate + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + instance method Template#evaluate +

    + + + + +
    +
    +
    +
    +
    +
    Template#evaluate(object) → String
    + + +

    Applies the template to object's data, producing a formatted string +with symbols replaced by object's corresponding properties.

    + +
    Examples
    + +
    var hrefTemplate = new Template('/dir/showAll?lang=#{language}&amp;categ=#{category}&amp;lv=#{levels}');
    +var selection = {category: 'books' , language: 'en-US'};
    + hrefTemplate.evaluate(selection);
    +// -> '/dir/showAll?lang=en-US&amp;categ=books&amp;lv='
    + hrefTemplate.evaluate({language: 'jp', levels: 3, created: '10/12/2005'});
    +// -> '/dir/showAll?lang=jp&amp;categ=&amp;lv=3'
    + hrefTemplate.evaluate({});
    +// -> '/dir/showAll?lang=&amp;categ=&amp;lv='
    + hrefTemplate.evaluate(null);
    +// -> error !
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/language/try/index.html b/doc/language/try/index.html new file mode 100644 index 000000000..7ed0b256f --- /dev/null +++ b/doc/language/try/index.html @@ -0,0 +1,144 @@ + + + + + Prototype v1.7_rc1 API documentation | Try + + + + + + + + + + + + + + + + +
    + +
    + + + + + +

    src code

    + +

    + namespace Try +

    + + + + + + + + + + + + + +
    +
    +

    Class methods

    +
    +
    + + +
    +
    + + +
    + + + +
    + + diff --git a/doc/language/try/these/index.html b/doc/language/try/these/index.html new file mode 100644 index 000000000..c173b73c9 --- /dev/null +++ b/doc/language/try/these/index.html @@ -0,0 +1,183 @@ + + + + + Prototype v1.7_rc1 API documentation | Try.these + + + + + + + + + + + + + + + + +
    + +
    + + +
    Deprecated
    + + + +

    src code

    + +

    + class method Try.these +

    + + + + +
    +
    +
    +
    +
    +
    Try.these(function...) → ?
    +
      +
    • + function + (Function) + – A function that may throw an exception. +
    • +
    + + +

    Accepts an arbitrary number of functions and returns the result of the +first one that doesn't throw an error.

    + +

    This method is deprecated.

    + +
    More information
    + +

    Try.these provides a simple idiom for trying out blocks of code in +sequence. Such a sequence of attempts usually represents a downgrading +approach to obtaining a given feature.

    + +

    In this example from Prototype's Ajax internals, we want to get an +XMLHttpRequest object. Internet Explorer 6 and earlier, however, does not +provide it as a vanilla JavaScript object, and will throw an error if we +attempt a simple instantiation. Also, over time, its proprietary way +evolved, changing COM interface names.

    + +

    Try.these will try several ways in sequence, from the best (and, +theoretically, most widespread) one to the oldest and rarest way, returning +the result of the first successful function.

    + +

    If none of the blocks succeeded, Try.these will return undefined, which +will cause the Ajax.getTransport method in the example below to return +false, provided as a fallback result value.

    + +
    var Ajax = {
    +  getTransport: function() {
    +    return Try.these(
    +      function() { return new XMLHttpRequest() },
    +      function() { return new ActiveXObject('Msxml2.XMLHTTP') },
    +      function() { return new ActiveXObject('Microsoft.XMLHTTP') }
    +    ) || false;
    +  }
    +};
    +
    +
    + + + + + +
    +
    +
    + +
    + + + +
    + + diff --git a/doc/stylesheets/api.css b/doc/stylesheets/api.css new file mode 100644 index 000000000..7e28842f8 --- /dev/null +++ b/doc/stylesheets/api.css @@ -0,0 +1,687 @@ +/* The "section" class implicitly needs a clearfix; adding it here for convenience. */ + +.clearfix:after, +.section:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; +} + +.clearfix, .section { + display: inline-block; +} + +html[xmlns] .clearfix, +html[xmlns] .section { + display: block; +} + +* html .clearfix, +* html .section { + height: 1%; +} + +span.replaced { visibility: hidden; } +span.hidden { display: none; } + + +body { + font-family: Verdana, sans-serif; + font-size: 82.5%; + line-height: 1.5em; + margin: 0; + padding: 0; +} + + body * { + margin: 0; + padding: 0; + } + +h1, h2, h3, h4, h5, h6 { + font-family: "Helvetica Neue", Arial, Helvetica, sans-serif; +} + +pre { + white-space: pre-wrap; /* CSS 3 */ + white-space: -moz-pre-wrap; /* Mozilla, since 1999 */ + white-space: -pre-wrap; /* Opera 4-6 */ + white-space: -o-pre-wrap; /* Opera 7 */ + word-wrap: break-word; /* Internet Explorer 5.5+ */ +} + +a img { + border: 0; +} + +ul, li { + list-style-type: none; +} + +ol, ul { + margin: 0 0 15px; +} + +code, pre { + font-family: "Panic Sans", "Bitstream Vera Sans Mono", Monaco, Consolas, Andale Mono, monospace; + font-size: 12px; +} + +#page a.img, +#page a.img:link, +#page a.img:visited { + border: 0; +} + +.content { + padding-left: 120px; + margin: 0 auto; +} + +#page { + margin: 0; + position: fixed; + top: 0; + bottom: 0; + right: 0; + left: 241px; + overflow-y: scroll; + overflow-x: auto; +} + + +/* MASTHEAD */ + +.masthead { + margin-top: 31px; + height: 75px; + padding: 1px 0; + background: url(../images/header-stripe-small.png) repeat-x; +} + +h1.logo { + width: 236px; + height: 150px; + background: url(../images/header-logo-small.png) no-repeat; +} + + h1.logo a { + text-decoration: none; + } + +/* BREADCRUMBS */ + +ul.breadcrumbs { + margin-left: 120px; + padding-left: 120px; + list-style-type: none; +} + + ul.breadcrumbs li { + float: left; + list-style-type: none; + margin-left: 0; + margin-right: 0.4em; + } + +#deprecated { + position: absolute; + right: 0; + top: 0; +} + +#deprecated img { + display: block; + border: 0; +} + + +/* PAGE CONTENT */ + +.page-content { + width: 715px; + margin: 0 0 30px 0; +} + + .page-content h2.page-title { + margin: 0 0 15px 120px; + line-height: 100%; + font-size: 27px; + letter-spacing: -1px; + color: #444; + } + + .page-introduction { + margin-left: 120px; + margin-bottom: 25px; + } + + .page-content a, + .page-content a:link { + color: #036; + border-bottom: 1px solid #036; + text-decoration: none; + } + + .page-content a:visited { + border-bottom: 1px solid #bbb; + } + + .page-content ul, + .page-content ol { + margin: 10px 0; + } + + .page-content li { + margin: 5px 0 8px 20px; + list-style-type: disc; + } + + .page-content p { + margin: 0 0 0.8em; + } + + .page-content code { + background-color: #f0f0f0; + border: 1px solid #ccc; + border-radius: 3px; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + padding: 0 3px; + } + + .page-content pre { + color: #333; + background-color: #f0f0ff; + border: 1px solid #dde; + padding: 3px 5px; + margin: 0 0 1em; + } + + .page-content pre code { + background-color: transparent; + border: 0; + padding: 0; + line-height: 100%; + } + + + .page-content code { + + } + + .page-content h1 { + font-size: 27px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h2 { + font-size: 23px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h3 { + font-size: 20px; + color: #000; + margin: 1.0em 0 0.6em; + } + + .page-content h4 { + font-size: 17px; + color: #555; + margin: 1.0em 0 0.6em; + } + + .page-content h5 { + font-size: 15px; + color: #2a2a2a; + margin: 1.0em 0 0.6em; + } + + .page-content h6 { + font-size: 14px; + color: #000; + margin: 1.0em 0 0.6em; + } + +/* PAGE SECTIONS */ + +.section { + margin: 10px 0 15px; +} + + .section-title { + width: 110px; + float: left; + margin-right: 10px; + padding-right: 0; + padding-bottom: 10px; + text-align: right; + overflow: hidden; + } + + .section-title h3 { + color: #999; + font-size: 14px; + line-height: 110%; + margin-top: 3px; + padding-right: 10px; + padding-bottom: 5px; + } + + .section-content { + width: 595px; + float: left; + } + + +/* API STYLES */ + +.page-title .type { + display: block; + text-transform: uppercase; + font-size: 14px; + color: #aaa; +} + + +ul.section-list { + list-style-type: none; + margin-top: 0; +} + + ul.section-list li { + list-style-type: none; + margin: 0 0 15px; + } + + ul.section-list li h4 { + margin-top: 0; + } + +ul.method-list { + margin-top: 0; +} + + ul.method-list li { + float: left; + margin: 0 5px 3px 0; + list-style-type: none; + padding-bottom: 0; + } + + ul.method-list li a, + ul.method-list li a:link { + text-decoration: none; + border: 0; + } + +ul.method-details-list { + margin-top: 0; +} + + li.method-description { + margin: 0 0 2.0em; + list-style-type: none; + } + + .method-description h4 { + margin: 0 0 0.6em; + line-height: 90%; + } + + .method-description p { + margin: 0.8em 0; + } + + + .method-description .method-permalink a { + color: #aaa; + text-decoration: none; + border-bottom: 0; + font-size: 14px; +} + +h4.inherited { + clear: left; + font-size: 15px; + font-style: italic; +} + +pre.syntax { + margin-bottom: 5px; +} + +ul.argument-list { + font-size: 12px; + padding: 0; + margin: 0; +} + + ul.argument-list li { + line-height: 140%; + margin-top: 0px; + margin-bottom: 5px; + } + + ul.argument-list li code { + font-size: 11px; + } + + ul.argument-list .argument-name { + background-color: #eeffee; + border-color: #6b6; + } + + +/* SECTION ICONS */ + +.page-content .section .section-title h3 { + padding-right: 24px; + background-position: right 0; + background-repeat: no-repeat; +} + +.section-constructor .section-title h3 { + background-image: url(../images/constructor.png); +} + +.section-method-list .section-title h3 { + background-image: url(../images/method.png); +} + +.section-class_methods .section-title h3 { + background-image: url(../images/class_method.png); +} + +.section-class_properties .section-title h3 { + background-image: url(../images/class_property.png); +} + +.section-instance_methods .section-title h3 { + background-image: url(../images/instance_method.png); +} + +.section-instance_properties .section-title h3 { + background-image: url(../images/instance_property.png); +} + +.section-mixins .section-title h3 { + background-image: url(../images/mixin.png); +} + +.section-classes .section-title h3 { + background-image: url(../images/class.png); +} + +.section-namespaces .section-title h3 { + background-image: url(../images/namespace.png); +} + +.section-sections .section-title h3 { + background-image: url(../images/section.png); +} + +.section-utilities .section-title h3 { + background-image: url(../images/utility.png); +} + +.section-description .section-title h3 { + background-image: url(../images/description.png); +} + +.section-subclasses .section-title h3 { + background-image: url(../images/subclass.png); +} + +.section-superclass .section-title h3 { + background-image: url(../images/superclass.png); +} + +/* notes */ + +p.note, +p.alias, +p.related-to { + font-size: 11px; + line-height: 14px; + padding: 5px 20px 5px 60px; + background-repeat: no-repeat; + background-position: 20px 50%; + border: 1px solid #000; +} + +p.note { + background-color: #f0f0f4; + background-image: url(../images/information.png); + border-color: #69c; +} + +p.alias { + background-color: #fff6de; + background-image: url(../images/alias.png); + border-color: #cc9; +} + +p.related-to { + background-color: #f4f0f4; + background-image: url(../images/related_to.png); + border-color: #c9c; +} + +/* SIDEBAR */ + +#sidebar { + position: fixed; + top: 0; + bottom: 0; + left: 0; + width: 240px; + background: #fff; + font-size: 13px; +} + +#sidebar form.search-ribbon { + margin: 0; + height: 24px; + border-right: 1px solid #636363; + padding: 4px 0 3px; + border-bottom: 1px solid #587e93; + background: url(../images/search-background.png) repeat-x 0 0; + text-align: center; +} + +/* Keep these around for `Control.Tabs`. */ +.sidebar-tabs { display: none; } + +.menu-items ul { + margin: 0; +} + + .menu-items ul li { + list-style-type: none; + padding-left: 0; + margin-left: 0; + } + + .menu-items ul .menu-item a { + padding-left: 38px; + background-position: 16px 50%; + } + + .menu-items ul ul .menu-item a { + padding-left: 48px; + background-position: 26px 50%; + } + + .menu-items ul ul ul .menu-item a { + padding-left: 58px; + background-position: 36px 50%; + } + + .menu-items ul ul ul ul .menu-item a { + padding-left: 68px; + background-position: 46px 50%; + } + + + + .menu-item a, + .menu-item a:link { + display: block; + padding: 3px 10px 3px 28px; + background-position: 6px 50%; + background-repeat: no-repeat; + text-align: left; + text-decoration: none; + color: #333; + border-top: 1px solid #fff; + border-bottom: 1px solid #fff; + white-space: nowrap; + } + + .menu-item a:hover, + .menu-item a.highlighted, + #sidebar .highlighted a { + border-top: 1px solid #69f; + border-bottom: 1px solid #69f; + background-color: #f0f0ff; + } + + .menu-item a.current, + #sidebar .current a { + border-top: 1px solid #f0f0ff; + border-bottom: 1px solid #f0f0ff; + background-color: #f0f0ff; + } + + .menu-item a.current-parent, + #sidebar .current-parent a { + border-top: 1px solid #f0f0ff; + border-bottom: 1px solid #f0f0ff; + background-color: #f0f0ff; + } + + .menu-item a.class-method { + background-image: url(../images/class_method.png); + } + + .menu-item a.instance-method { + background-image: url(../images/instance_method.png); + } + + .menu-item a.class { + background-image: url(../images/class.png); + } + + .menu-item a.constructor { + background-image: url(../images/constructor.png); + } + + .menu-item a.class-property { + background-image: url(../images/class_property.png); + } + + .menu-item a.instance-property { + background-image: url(../images/instance_property.png); + } + + .menu-item a.namespace { + background-image: url(../images/namespace.png); + } + + .menu-item a.mixin { + background-image: url(../images/mixin.png); + } + + .menu-item a.utility { + background-image: url(../images/utility.png); + } + + .menu-item a.section { + margin: 0; + background-image: url(../images/section.png); + } + + #api_menu .menu-item a.section { + height: 22px; + font-weight: normal; + color: #a5a5a5; + margin-top: 0; + margin-bottom: 0; + border-top: 1px solid #000; + border-bottom: 1px solid #000; + background: url(../images/section-background.png) repeat-x 0 0; + } + +.menu-section { + margin-bottom: 1.0em; +} + +#menu_pane { + position: absolute; + top: 32px; + bottom: 0; + left: 0; + width: 239px; + border-right: 1px solid #636363; + overflow-y: scroll; + overflow-x: hidden; +} + +#search_pane { + width: 239px; + border-right: 1px solid #636363; + position: absolute; + top: 32px; + bottom: 0; + left: 0; +} + + #search_results { + margin: 0; + padding: 0; + overflow-y: scroll; + overflow-x: hidden; + position: absolute; + top: 0; + bottom: 0; + width: 239px; + } + +#search { + width: 200px; + padding: 2px 3px; +} + +input.ghosted { + font-style: italic; + color: #aaa; +} + + +/* FOOTER */ + +#footer { + color: #bbb; + width: 595px; + margin-left: 120px; + margin-top: 30px; + border-top: 1px solid #ccc; + font-size: 10px; + padding: 1em 0; +} + + #footer a, + #footer a:link { + color: #999; + } + +#src_code_href { + float: right; +} \ No newline at end of file diff --git a/doc/stylesheets/pygments.css b/doc/stylesheets/pygments.css new file mode 100644 index 000000000..56dee2899 --- /dev/null +++ b/doc/stylesheets/pygments.css @@ -0,0 +1,62 @@ +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #408080; font-style: italic } /* Comment */ +.highlight .err { border: 1px solid #FF0000 } /* Error */ +.highlight .k { color: #008000; font-weight: bold } /* Keyword */ +.highlight .o { color: #666666 } /* Operator */ +.highlight .cm { color: #408080; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #BC7A00 } /* Comment.Preproc */ +.highlight .c1 { color: #408080; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #408080; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A00000 } /* Generic.Deleted */ +.highlight .ge { font-style: italic } /* Generic.Emph */ +.highlight .gr { color: #FF0000 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #808080 } /* Generic.Output */ +.highlight .gp { color: #000080; font-weight: bold } /* Generic.Prompt */ +.highlight .gs { font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #0040D0 } /* Generic.Traceback */ +.highlight .kc { color: #008000; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #008000; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #008000; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #008000 } /* Keyword.Pseudo */ +.highlight .kr { color: #008000; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #B00040 } /* Keyword.Type */ +.highlight .m { color: #666666 } /* Literal.Number */ +.highlight .s { color: #BA2121 } /* Literal.String */ +.highlight .na { color: #7D9029 } /* Name.Attribute */ +.highlight .nb { color: #008000 } /* Name.Builtin */ +.highlight .nc { color: #0000FF; font-weight: bold } /* Name.Class */ +.highlight .no { color: #880000 } /* Name.Constant */ +.highlight .nd { color: #AA22FF } /* Name.Decorator */ +.highlight .ni { color: #999999; font-weight: bold } /* Name.Entity */ +.highlight .ne { color: #D2413A; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #0000FF } /* Name.Function */ +.highlight .nl { color: #A0A000 } /* Name.Label */ +.highlight .nn { color: #0000FF; font-weight: bold } /* Name.Namespace */ +.highlight .nt { color: #008000; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #19177C } /* Name.Variable */ +.highlight .ow { color: #AA22FF; font-weight: bold } /* Operator.Word */ +.highlight .w { color: #bbbbbb } /* Text.Whitespace */ +.highlight .mf { color: #666666 } /* Literal.Number.Float */ +.highlight .mh { color: #666666 } /* Literal.Number.Hex */ +.highlight .mi { color: #666666 } /* Literal.Number.Integer */ +.highlight .mo { color: #666666 } /* Literal.Number.Oct */ +.highlight .sb { color: #BA2121 } /* Literal.String.Backtick */ +.highlight .sc { color: #BA2121 } /* Literal.String.Char */ +.highlight .sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #BA2121 } /* Literal.String.Double */ +.highlight .se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */ +.highlight .sh { color: #BA2121 } /* Literal.String.Heredoc */ +.highlight .si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */ +.highlight .sx { color: #008000 } /* Literal.String.Other */ +.highlight .sr { color: #BB6688 } /* Literal.String.Regex */ +.highlight .s1 { color: #BA2121 } /* Literal.String.Single */ +.highlight .ss { color: #19177C } /* Literal.String.Symbol */ +.highlight .bp { color: #008000 } /* Name.Builtin.Pseudo */ +.highlight .vc { color: #19177C } /* Name.Variable.Class */ +.highlight .vg { color: #19177C } /* Name.Variable.Global */ +.highlight .vi { color: #19177C } /* Name.Variable.Instance */ +.highlight .il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/ext/update_helper/prototype_update_helper.html b/ext/update_helper/prototype_update_helper.html deleted file mode 100644 index 625911d5d..000000000 --- a/ext/update_helper/prototype_update_helper.html +++ /dev/null @@ -1,339 +0,0 @@ - - - - Prototype Unit test file - - - - - - - -

    Prototype Unit test file

    -

    - Test of deprecation.js -

    - -
    foo
    -
    bar
    -
    bla
    - - -
    - - - - - - diff --git a/ext/update_helper/update_helper.js b/ext/update_helper/update_helper.js deleted file mode 100644 index 2a4b7b6c4..000000000 --- a/ext/update_helper/update_helper.js +++ /dev/null @@ -1,78 +0,0 @@ -/* Update Helper (c) 2008-2009 Tobie Langel - * - * Requires Prototype >= 1.6.0 - * - * Update Helper is distributable under the same terms as Prototype - * (MIT-style license). For details, see the Prototype web site: - * http://www.prototypejs.org/ - * - *--------------------------------------------------------------------------*/ - -var UpdateHelper = Class.create({ - logLevel: 0, - MessageTemplate: new Template('Update Helper: #{message}\n#{stack}'), - Regexp: new RegExp("@" + window.location.protocol + ".*?\\d+\\n", "g"), - - initialize: function(deprecatedMethods) { - var notify = function(message, type) { - this.notify(message, type); - }.bind(this); // Late binding to simplify testing. - - deprecatedMethods.each(function(d) { - var condition = d.condition, - type = d.type || 'info', - message = d.message, - namespace = d.namespace, - method = d.methodName; - - namespace[method] = (namespace[method] || function() {}).wrap(function(proceed) { - var args = $A(arguments).splice(1); - if (!condition || condition.apply(this, args)) notify(message, type); - return proceed.apply(proceed, args); - }); - }); - Element.addMethods(); - }, - - notify: function(message, type) { - switch(type) { - case 'info': - if (this.logLevel > UpdateHelper.Info) return false; - case 'warn': - if (this.logLevel > UpdateHelper.Warn) return false; - default: - if (this.logLevel > UpdateHelper.Error) return false; - } - this.log(this.MessageTemplate.evaluate({ - message: message, - stack: this.getStack() - }), type); - return true; - }, - - getStack: function() { - try { - throw new Error("stack"); - } catch(e) { - var match = (e.stack || '').match(this.Regexp); - if (match) { - return match.reject(function(path) { - return (/(prototype|unittest|update_helper)\.js/).test(path); - }).join("\n"); - } else { return ''; } - } - }, - - log: function(message, type) { - if (type == 'error') console.error(message); - else if (type == 'warn') console.warn(message); - else console.log(message); - } -}); - -Object.extend(UpdateHelper, { - Info: 0, - Warn: 1, - Error: 2 -}); - diff --git a/images/gravatar_placeholder.png b/images/gravatar_placeholder.png new file mode 100644 index 000000000..94a10afcc Binary files /dev/null and b/images/gravatar_placeholder.png differ diff --git a/images/header-logo-small.png b/images/header-logo-small.png new file mode 100644 index 000000000..f377977fb Binary files /dev/null and b/images/header-logo-small.png differ diff --git a/images/header-stripe-small.png b/images/header-stripe-small.png new file mode 100644 index 000000000..e10464063 Binary files /dev/null and b/images/header-stripe-small.png differ diff --git a/index.html b/index.html new file mode 100644 index 000000000..f4f080920 --- /dev/null +++ b/index.html @@ -0,0 +1 @@ +Nothing to see here... diff --git a/src/constants.yml b/src/constants.yml deleted file mode 100644 index 2532f981c..000000000 --- a/src/constants.yml +++ /dev/null @@ -1 +0,0 @@ -PROTOTYPE_VERSION: 1.7.3 diff --git a/src/prototype.js b/src/prototype.js deleted file mode 100644 index f493a7475..000000000 --- a/src/prototype.js +++ /dev/null @@ -1,6 +0,0 @@ -//= compat -//= require "./prototype/prototype" -//= require "./prototype/lang" -//= require "./prototype/ajax" -//= require "./prototype/dom" -//= require "./prototype/deprecated" diff --git a/src/prototype/ajax.js b/src/prototype/ajax.js deleted file mode 100644 index abee64c6f..000000000 --- a/src/prototype/ajax.js +++ /dev/null @@ -1,129 +0,0 @@ -//= compat -//= require "ajax/ajax" -//= require "ajax/responders" -//= require "ajax/base" -//= require "ajax/request" -//= require "ajax/response" -//= require "ajax/updater" -//= require "ajax/periodical_updater" - -/** - * == Ajax == - * - * Prototype's APIs around the `XmlHttpRequest` object. - * - * The Prototype framework enables you to deal with Ajax calls in a manner that - * is both easy and compatible with all modern browsers. - * - * Actual requests are made by creating instances of [[Ajax.Request]]. - * - * ##### Request headers - * - * The following headers are sent with all Ajax requests (and can be - * overridden with the `requestHeaders` option described below): - * - * * `X-Requested-With` is set to `XMLHttpRequest`. - * * `X-Prototype-Version` is set to Prototype's current version (e.g., - * `<%= PROTOTYPE_VERSION %>`). - * * `Accept` is set to `text/javascript, text/html, application/xml, - * text/xml, * / *` - * * `Content-type` is automatically determined based on the `contentType` - * and `encoding` options. - * - * ##### Ajax options - * - * All Ajax classes share a common set of _options_ and _callbacks_. - * Callbacks are called at various points in the life-cycle of a request, and - * always feature the same list of arguments. - * - * ##### Common options - * - * * `asynchronous` ([[Boolean]]; default `true`): Determines whether - * `XMLHttpRequest` is used asynchronously or not. Synchronous usage is - * **strongly discouraged** — it halts all script execution for the - * duration of the request _and_ blocks the browser UI. - * * `body` ([[String]]): Specific contents for the request body on a - * method that sends a payload (like `post` or `put`). If it is not - * provided, the contents of the `parameters` option will be used instead. - * * `contentType` ([[String]]; default `application/x-www-form-urlencoded`): - * The `Content-type` header for your request. Change this header if you - * want to send data in another format (like XML). - * * `encoding` ([[String]]; default `UTF-8`): The encoding for the contents - * of your request. It is best left as-is, but should weird encoding issues - * arise, you may have to tweak this. - * * `method` ([[String]]; default `post`): The HTTP method to use for the - * request. The other common possibility is `get`. Abiding by Rails - * conventions, Prototype also reacts to other HTTP verbs (such as `put` and - * `delete`) by submitting via `post` and adding a extra `_method` parameter - * with the originally-requested method. - * * `parameters` ([[String]]): The parameters for the request, which will be - * encoded into the URL for a `get` method, or into the request body for the - * other methods. This can be provided either as a URL-encoded string, a - * [[Hash]], or a plain [[Object]]. - * * `postBody` ([[String]]): An alias for `body` that is provided for - * backward-compatibility. Its use is discouraged. - * * `requestHeaders` ([[Object]]): A set of key-value pairs, with properties - * representing header names. - * * `evalJS` ([[Boolean]] | [[String]]; default `true`): Automatically `eval`s - * the content of [[Ajax.Response#responseText]] if the `Content-type` returned - * by the server is set to one of `text/javascript`, `application/ecmascript` - * (matches expression `(text|application)\/(x-)?(java|ecma)script`). - * If the request doesn't obey same-origin policy, the content is not evaluated. - * If you need to force evalutation, pass `'force'`. To prevent it altogether, - * pass `false`. - * * `evalJSON` ([[Boolean]] | [[String]]; default `true`): Automatically `eval`s - * the content of [[Ajax.Response#responseText]] and populates - * [[Ajax.Response#responseJSON]] with it if the `Content-type` returned by - * the server is set to `application/json`. If the request doesn't obey - * same-origin policy, the content is sanitized before evaluation. If you - * need to force evalutation, pass `'force'`. To prevent it altogether, pass - * `false`. - * * `sanitizeJSON` ([[Boolean]]; default is `false` for same-origin requests, - * `true` otherwise): Sanitizes the contents of - * [[Ajax.Response#responseText]] before evaluating it. - * - * ##### Common callbacks - * - * When used on individual instances, all callbacks (except `onException`) are - * invoked with two parameters: the [[Ajax.Response]] object and the result of - * evaluating the `X-JSON` response header, if any (can be `null`). - * - * For another way of describing their chronological order and which callbacks - * are mutually exclusive, see [[Ajax.Request]]. - * - * * `onCreate`: Triggered when the [[Ajax.Request]] object is initialized. - * This is _after_ the parameters and the URL have been processed, but - * _before_ opening the connection via the XHR object. - * * `onUninitialized` (*Not guaranteed*): Invoked just after the XHR object - * is created. - * * `onLoading` (*Not guaranteed*): Triggered when the underlying XHR object - * is being setup, and its connection opened. - * * `onLoaded` (*Not guaranteed*): Triggered once the underlying XHR object - * is setup, the connection is open, and it is ready to send its actual - * request. - * * `onInteractive` (*Not guaranteed*): Triggered whenever the requester - * receives a part of the response (but not the final part), should it - * be sent in several packets. - * * `onSuccess`: Invoked when a request completes and its status code is - * `undefined` or belongs in the `2xy` family. This is skipped if a - * code-specific callback is defined (e.g., `on200`), and happens _before_ - * `onComplete`. - * * `onFailure`: Invoked when a request completes and its status code exists - * but _is not_ in the `2xy` family. This is skipped if a code-specific - * callback is defined (e.g. `on403`), and happens _before_ `onComplete`. - * * `onXYZ` (_with `XYZ` representing any HTTP status code_): Invoked just - * after the response is complete _if_ the status code is the exact code - * used in the callback name. _Prevents_ execution of `onSuccess` and - * `onFailure`. Happens _before_ `onComplete`. - * * `onException`: Triggered whenever an XHR error arises. Has a custom - * signature: the first argument is the requester (i.e. an [[Ajax.Request]] - * instance), and the second is the exception object. The default - * `onException` handler simply re-throws the caught exception. (If you - * want exceptions to be silently ignored, pass in an empty function to - * `onException`.) - * * `onComplete`: Triggered at the _very end_ of a request's life-cycle, after - * the request completes, status-specific callbacks are called, and possible - * automatic behaviors are processed. Guaranteed to run regardless of what - * happened during the request. - * -**/ diff --git a/src/prototype/ajax/ajax.js b/src/prototype/ajax/ajax.js deleted file mode 100644 index ab79023f4..000000000 --- a/src/prototype/ajax/ajax.js +++ /dev/null @@ -1,17 +0,0 @@ -/** section: Ajax - * Ajax -**/ - -var Ajax = { - getTransport: function() { - return new XMLHttpRequest(); - }, - - /** - * Ajax.activeRequestCount -> Number - * - * Represents the number of active XHR requests triggered through - * [[Ajax.Request]], [[Ajax.Updater]], or [[Ajax.PeriodicalUpdater]]. - **/ - activeRequestCount: 0 -}; diff --git a/src/prototype/ajax/base.js b/src/prototype/ajax/base.js deleted file mode 100644 index 791cbcc0b..000000000 --- a/src/prototype/ajax/base.js +++ /dev/null @@ -1,23 +0,0 @@ -// Abstract class; does not need documentation. -Ajax.Base = Class.create({ - initialize: function(options) { - this.options = { - method: 'post', - asynchronous: true, - contentType: 'application/x-www-form-urlencoded', - encoding: 'UTF-8', - parameters: '', - evalJSON: true, - evalJS: true, - onException: function (request, error) { - throw error; - } - }; - Object.extend(this.options, options || { }); - - this.options.method = this.options.method.toLowerCase(); - - if (Object.isHash(this.options.parameters)) - this.options.parameters = this.options.parameters.toObject(); - } -}); diff --git a/src/prototype/ajax/periodical_updater.js b/src/prototype/ajax/periodical_updater.js deleted file mode 100644 index 5d2df01f9..000000000 --- a/src/prototype/ajax/periodical_updater.js +++ /dev/null @@ -1,260 +0,0 @@ -/** section: Ajax - * class Ajax.PeriodicalUpdater - * - * Periodically performs an Ajax request and updates a container's contents - * based on the response text. - * - * [[Ajax.PeriodicalUpdater]] behaves like [[Ajax.Updater]], but performs the - * update at a prescribed interval, rather than only once. (Note that it is - * _not_ a subclass of [[Ajax.Updater]]; it's a wrapper around it.) - * - * This class addresses the common need of periodical update, as required by - * all sorts of "polling" mechanisms (e.g., an online chatroom or an online - * mail client). - * - * The basic idea is to run a regular [[Ajax.Updater]] at regular intervals, - * keeping track of the response text so it can (optionally) react to - * receiving the exact same response consecutively. - * - * ##### Additional options - * - * [[Ajax.PeriodicalUpdater]] features all the common options and callbacks - * described in the [[Ajax section]] — _plus_ those added by - * [[Ajax.Updater]]. - * - * It also provides two new options: - * - * * `frequency` ([[Number]]; default is `2`): How long, in seconds, to wait - * between the end of one request and the beginning of the next. - * * `decay` ([[Number]]; default is `1`): The rate at which the `frequency` - * grows when the response received is _exactly_ the same as the previous. - * The default of `1` means `frequency` will never grow; override the - * default if a stale response implies it's worthwhile to poll less often. - * If `decay` is set to `2`, for instance, `frequency` will double - * (2 seconds, 4 seconds, 8 seconds...) each consecutive time the result - * is the same; when the result is different once again, `frequency` will - * revert to its original value. - * - * ##### Disabling and re-enabling a [[Ajax.PeriodicalUpdater]] - * - * You can hit the brakes on a running [[Ajax.PeriodicalUpdater]] by calling - * [[Ajax.PeriodicalUpdater#stop]]. If you wish to re-enable it later, call - * [[Ajax.PeriodicalUpdater#start]]. - * -**/ - -Ajax.PeriodicalUpdater = Class.create(Ajax.Base, { - /** - * new Ajax.PeriodicalUpdater(container, url[, options]) - * - container (String | Element): The DOM element whose contents to update - * as a result of the Ajax request. Can be a DOM node or a string that - * identifies a node's ID. - * - url (String): The URL to fetch. When the _same-origin_ policy is in - * effect (as it is in most cases), `url` **must** be a relative URL or an - * absolute URL that starts with a slash (i.e., it must not begin with - * `http`). - * - options (Object): Configuration for the request. See the - * [[Ajax section]] for more information. - * - * Creates a new [[Ajax.PeriodicalUpdater]]. - * - * Periodically performs an AJAX request and updates a container's contents - * based on the response text. Offers a mechanism for "decay," which lets it - * trigger at widening intervals while the response is unchanged. - * - * This object addresses the common need of periodical update, which is used - * by all sorts of "polling" mechanisms (e.g. in an online chatroom or an - * online mail client). - * - * The basic idea is to run a regular [[Ajax.Updater]] at - * regular intervals, monitoring changes in the response text if the `decay` - * option (see below) is active. - * - * ##### Additional options - * - * [[Ajax.PeriodicalUpdater]] features all the common options and callbacks - * (see the [[Ajax section]] for more information), plus those added by - * [[Ajax.Updater]]. It also provides two new options that deal with the - * original period, and its decay rate (how Rocket Scientist does that make - * us sound, uh?!). - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    OptionDefaultDescription
    frequency2Okay, this is not a frequency (e.g 0.5Hz), but a period (i.e. a number of seconds). - * Don't kill me, I didn't write this one! This is the minimum interval at which AJAX - * requests are made. You don't want to make it too short (otherwise you may very well - * end up with multiple requests in parallel, if they take longer to process and return), - * but you technically can provide a number below one, e.g. 0.75 second.
    decay1This controls the rate at which the request interval grows when the response is - * unchanged. It is used as a multiplier on the current period (which starts at the original - * value of the frequency parameter). Every time a request returns an unchanged - * response text, the current period is multiplied by the decay. Therefore, the default - * value means regular requests (no change of interval). Values higher than one will - * yield growing intervals. Values below one are dangerous: the longer the response text - * stays the same, the more often you'll check, until the interval is so short your browser - * is left with no other choice than suicide. Note that, as soon as the response text - * does change, the current period resets to the original one.
    - * - * To better understand decay, here is a small sequence of calls from the - * following example: - * - * new Ajax.PeriodicalUpdater('items', '/items', { - * method: 'get', frequency: 3, decay: 2 - * }); - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Call#When?Decay beforeResponse changed?Decay afterNext periodComments
    100:002n/a13Response is deemed changed, since there is no prior response to compare to!
    200:031yes13Response did change again: we "reset" to 1, which was already the decay.
    300:061no26Response didn't change: decay augments by the decay option factor: - * we're waiting longer now…
    400:122no412Still no change, doubling again.
    500:244no824Jesus, is this thing going to change or what?
    600:488yes13Ah, finally! Resetting decay to 1, and therefore using the original period.
    - * - * ##### Disabling and re-enabling a [[Ajax.PeriodicalUpdater]] - * - * You can pull the brake on a running [[Ajax.PeriodicalUpdater]] by simply - * calling its `stop` method. If you wish to re-enable it later, just call - * its `start` method. Both take no argument. - * - * ##### Beware! Not a specialization! - * - * [[Ajax.PeriodicalUpdater]] is not a specialization of [[Ajax.Updater]], - * despite its name. When using it, do not expect to be able to use methods - * normally provided by [[Ajax.Request]] and "inherited" by [[Ajax.Updater]], - * such as `evalJSON` or `getHeader`. Also the `onComplete` callback is - * hijacked to be used for update management, so if you wish to be notified - * of every successful request, use `onSuccess` instead (beware: it will get - * called *before* the update is performed). - **/ - initialize: function($super, container, url, options) { - $super(options); - this.onComplete = this.options.onComplete; - - this.frequency = (this.options.frequency || 2); - this.decay = (this.options.decay || 1); - - this.updater = { }; - this.container = container; - this.url = url; - - this.start(); - }, - - /** - * Ajax.PeriodicalUpdater#start() -> undefined - * - * Starts the periodical updater (if it had previously been stopped with - * [[Ajax.PeriodicalUpdater#stop]]). - **/ - start: function() { - this.options.onComplete = this.updateComplete.bind(this); - this.onTimerEvent(); - }, - - /** - * Ajax.PeriodicalUpdater#stop() -> undefined - * - * Stops the periodical updater. - * - * Also calls the `onComplete` callback, if one has been defined. - **/ - stop: function() { - this.updater.options.onComplete = undefined; - clearTimeout(this.timer); - (this.onComplete || Prototype.emptyFunction).apply(this, arguments); - }, - - updateComplete: function(response) { - if (this.options.decay) { - this.decay = (response.responseText == this.lastText ? - this.decay * this.options.decay : 1); - - this.lastText = response.responseText; - } - this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency); - }, - - onTimerEvent: function() { - this.updater = new Ajax.Updater(this.container, this.url, this.options); - } -}); diff --git a/src/prototype/ajax/request.js b/src/prototype/ajax/request.js deleted file mode 100644 index f4ecaa16e..000000000 --- a/src/prototype/ajax/request.js +++ /dev/null @@ -1,361 +0,0 @@ -/** section: Ajax - * class Ajax.Request - * - * Initiates and processes an Ajax request. - * - * [[Ajax.Request]] is a general-purpose class for making HTTP requests which - * handles the life-cycle of the request, handles the boilerplate, and lets - * you plug in callback functions for your custom needs. - * - * In the optional `options` hash, you usually provide an `onComplete` and/or - * `onSuccess` callback, unless you're in the edge case where you're getting a - * JavaScript-typed response, that will automatically be `eval`'d. - * - * For a full list of common options and callbacks, see "Ajax options" heading - * of the [[Ajax section]]. - * - * ##### A basic example - * - * new Ajax.Request('/your/url', { - * onSuccess: function(response) { - * // Handle the response content... - * } - * }); - * - * ##### Request life-cycle - * - * Underneath our nice requester objects lies, of course, `XMLHttpRequest`. The - * defined life-cycle is as follows: - * - * 1. Created - * 2. Initialized - * 3. Request sent - * 4. Response being received (can occur many times, as packets come in) - * 5. Response received, request complete - * - * As you can see under the "Ajax options" heading of the [[Ajax section]], - * Prototype's AJAX objects define a whole slew of callbacks, which are - * triggered in the following order: - * - * 1. `onCreate` (this is actually a callback reserved to [[Ajax.Responders]]) - * 2. `onUninitialized` (maps on Created) - * 3. `onLoading` (maps on Initialized) - * 4. `onLoaded` (maps on Request sent) - * 5. `onInteractive` (maps on Response being received) - * 6. `on`*XYZ* (numerical response status code), onSuccess or onFailure (see below) - * 7. `onComplete` - * - * The two last steps both map on *Response received*, in that order. If a - * status-specific callback is defined, it gets invoked. Otherwise, if - * `onSuccess` is defined and the response is deemed a success (see below), it - * is invoked. Otherwise, if `onFailure` is defined and the response is *not* - * deemed a success, it is invoked. Only after that potential first callback is - * `onComplete` called. - * - * ##### A note on portability - * - * Depending on how your browser implements `XMLHttpRequest`, one or more - * callbacks may never be invoked. In particular, `onLoaded` and - * `onInteractive` are not a 100% safe bet so far. However, the global - * `onCreate`, `onUninitialized` and the two final steps are very much - * guaranteed. - * - * ##### `onSuccess` and `onFailure`, the under-used callbacks - * - * Way too many people use [[Ajax.Request]] in a similar manner to raw XHR, - * defining only an `onComplete` callback even when they're only interested in - * "successful" responses, thereby testing it by hand: - * - * // This is too bad, there's better! - * new Ajax.Request('/your/url', { - * onComplete: function(response) { - * if (200 == response.status) - * // yada yada yada - * } - * }); - * - * First, as described below, you could use better "success" detection: success - * is generally defined, HTTP-wise, as either no response status or a "2xy" - * response status (e.g., 201 is a success, too). See the example below. - * - * Second, you could dispense with status testing altogether! Prototype adds - * callbacks specific to success and failure, which we listed above. Here's - * what you could do if you're only interested in success, for instance: - * - * new Ajax.Request('/your/url', { - * onSuccess: function(response) { - * // yada yada yada - * } - * }); - * - * ##### Automatic JavaScript response evaluation - * - * If an Ajax request follows the _same-origin policy_ **and** its response - * has a JavaScript-related `Content-type`, the content of the `responseText` - * property will automatically be passed to `eval`. - * - * In other words: you don't even need to provide a callback to leverage - * pure-JavaScript Ajax responses. This is the convention that drives Rails's - * RJS. - * - * The list of JavaScript-related MIME-types handled by Prototype is: - * - * * `application/ecmascript` - * * `application/javascript` - * * `application/x-ecmascript` - * * `application/x-javascript` - * * `text/ecmascript` - * * `text/javascript` - * * `text/x-ecmascript` - * * `text/x-javascript` - * - * The MIME-type string is examined in a case-insensitive manner. - * - * ##### Methods you may find useful - * - * Instances of the [[Ajax.Request]] object provide several methods that come - * in handy in your callback functions, especially once the request is complete. - * - * ###### Is the response a successful one? - * - * The [[Ajax.Request#success]] method examines the XHR object's `status` - * property and follows general HTTP guidelines: unknown status is deemed - * successful, as is the whole `2xy` status code family. It's a generally - * better way of testing your response than the usual - * `200 == transport.status`. - * - * ###### Getting HTTP response headers - * - * While you can obtain response headers from the XHR object using its - * `getResponseHeader` method, this makes for verbose code, and several - * implementations raise an exception when the header is not found. To make - * this easier, you can use the [[Ajax.Response#getHeader]] method, which - * delegates to the longer version and returns `null` if an exception occurs: - * - * new Ajax.Request('/your/url', { - * onSuccess: function(response) { - * // Note how we brace against null values - * if ((response.getHeader('Server') || '').match(/Apache/)) - * ++gApacheCount; - * // Remainder of the code - * } - * }); - * - * ##### Evaluating JSON headers - * - * Some backends will return JSON not as response text, but in the `X-JSON` - * header. In this case, you don't even need to evaluate the returned JSON - * yourself, as Prototype automatically does so. It passes the result as the - * `headerJSON` property of the [[Ajax.Response]] object. Note that if there - * is no such header — or its contents are invalid — `headerJSON` - * will be set to `null`. - * - * new Ajax.Request('/your/url', { - * onSuccess: function(transport) { - * transport.headerJSON - * } - * }); -**/ -Ajax.Request = Class.create(Ajax.Base, { - _complete: false, - - /** - * new Ajax.Request(url[, options]) - * - url (String): The URL to fetch. When the _same-origin_ policy is in - * effect (as it is in most cases), `url` **must** be a relative URL or an - * absolute URL that starts with a slash (i.e., it must not begin with - * `http`). - * - options (Object): Configuration for the request. See the - * [[Ajax section]] for more information. - * - * Creates a new `Ajax.Request`. - **/ - initialize: function($super, url, options) { - $super(options); - this.transport = Ajax.getTransport(); - this.request(url); - }, - - request: function(url) { - this.url = url; - this.method = this.options.method; - var params = Object.isString(this.options.parameters) ? - this.options.parameters : - Object.toQueryString(this.options.parameters); - - if (params && this.method === 'get') { - // when GET, append parameters to URL - this.url += (this.url.include('?') ? '&' : '?') + params; - } - - this.parameters = params.toQueryParams(); - - try { - var response = new Ajax.Response(this); - if (this.options.onCreate) this.options.onCreate(response); - Ajax.Responders.dispatch('onCreate', this, response); - - this.transport.open(this.method.toUpperCase(), this.url, - this.options.asynchronous); - - if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1); - - this.transport.onreadystatechange = this.onStateChange.bind(this); - this.setRequestHeaders(); - - if (this.method !== 'get') { - this.body = this.options.body || this.options.postBody || params; - } else { - this.body = null; - } - - this.transport.send(this.body); - - /* Force Firefox to handle ready state 4 for synchronous requests */ - if (!this.options.asynchronous && this.transport.overrideMimeType) - this.onStateChange(); - - } - catch (e) { - this.dispatchException(e); - } - }, - - onStateChange: function() { - var readyState = this.transport.readyState; - if (readyState > 1 && !((readyState == 4) && this._complete)) - this.respondToReadyState(this.transport.readyState); - }, - - setRequestHeaders: function() { - var headers = { - 'X-Requested-With': 'XMLHttpRequest', - 'X-Prototype-Version': Prototype.Version, - 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*' - }; - - if (this.method !== 'get') { - // Don't set the `Content-Type` header if the user has explicitly set - // `contentType` to anything falsy. - if (this.options.contentType) { - headers['Content-type'] = this.options.contentType + - (this.options.encoding ? '; charset=' + this.options.encoding : ''); - } - - /* Force "Connection: close" for older Mozilla browsers to work - * around a bug where XMLHttpRequest sends an incorrect - * Content-length header. See Mozilla Bugzilla #246651. - */ - if (this.transport.overrideMimeType && - (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) - headers['Connection'] = 'close'; - } - - // user-defined headers - if (typeof this.options.requestHeaders == 'object') { - var extras = this.options.requestHeaders; - - if (Object.isFunction(extras.push)) - for (var i = 0, length = extras.length; i < length; i += 2) - headers[extras[i]] = extras[i+1]; - else - $H(extras).each(function(pair) { headers[pair.key] = pair.value }); - } - - // skip null or undefined values - for (var name in headers) - if (headers[name] != null) - this.transport.setRequestHeader(name, headers[name]); - }, - - /** - * Ajax.Request#success() -> Boolean - * - * Tests whether the request was successful. - **/ - success: function() { - var status = this.getStatus(); - return !status || (status >= 200 && status < 300) || status == 304; - }, - - getStatus: function() { - try { - // IE sometimes returns 1223 for a 204 response. - if (this.transport.status === 1223) return 204; - return this.transport.status || 0; - } catch (e) { return 0 } - }, - - respondToReadyState: function(readyState) { - var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this); - - if (state == 'Complete') { - try { - this._complete = true; - (this.options['on' + response.status] - || this.options['on' + (this.success() ? 'Success' : 'Failure')] - || Prototype.emptyFunction)(response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } - - var contentType = response.getHeader('Content-type'); - if (this.options.evalJS == 'force' - || (this.options.evalJS && this.isSameOrigin() && contentType - && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i))) - this.evalResponse(); - } - - try { - (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON); - } catch (e) { - this.dispatchException(e); - } finally { - Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON); - } - - if (state == 'Complete') { - // avoid memory leak in MSIE: clean up - this.transport.onreadystatechange = Prototype.emptyFunction; - } - }, - - isSameOrigin: function() { - var m = this.url.match(/^\s*https?:\/\/[^\/]*/); - return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({ - protocol: location.protocol, - domain: document.domain, - port: location.port ? ':' + location.port : '' - })); - }, - - /** - * Ajax.Request#getHeader(name) -> String | null - * - name (String): The name of an HTTP header that may have been part of - * the response. - * - * Returns the value of the given response header, or `null` if that header - * was not found. - **/ - getHeader: function(name) { - try { - return this.transport.getResponseHeader(name) || null; - } catch (e) { return null; } - }, - - evalResponse: function() { - try { - return eval((this.transport.responseText || '').unfilterJSON()); - } catch (e) { - this.dispatchException(e); - } - }, - - dispatchException: function(exception) { - (this.options.onException || Prototype.emptyFunction)(this, exception); - Ajax.Responders.dispatch('onException', this, exception); - } -}); - -Ajax.Request.Events = - ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; diff --git a/src/prototype/ajax/responders.js b/src/prototype/ajax/responders.js deleted file mode 100644 index 0f5611e37..000000000 --- a/src/prototype/ajax/responders.js +++ /dev/null @@ -1,120 +0,0 @@ -/** section: Ajax - * Ajax.Responders - * includes Enumerable - * - * A repository of global listeners notified about every step of - * Prototype-based Ajax requests. - * - * Sometimes, you need to provide generic behaviors over all Ajax operations - * happening on the page (through [[Ajax.Request]], [[Ajax.Updater]] or - * [[Ajax.PeriodicalUpdater]]). - * - * For instance, you might want to automatically show an indicator when an - * Ajax request is ongoing, and hide it when none are. You may well want to - * factor out exception handling as well, logging those somewhere on the page - * in a custom fashion. The possibilities are myriad. - * - * To achieve this, Prototype provides `Ajax.Responders`, which lets you - * register (and, if you wish, unregister later) _responders_, which are - * objects with specially-named methods. These names come from a set of - * general callbacks corresponding to different points in time (or outcomes) - * of an Ajax request's life cycle. - * - * For instance, Prototype automatically registers a responder that maintains - * a nifty variable: [[Ajax.activeRequestCount]]. This represents, at a given - * time, the number of currently active Ajax requests — by monitoring their - * `onCreate` and `onComplete` events. The code for this is fairly simple: - * - * Ajax.Responders.register({ - * onCreate: function() { - * Ajax.activeRequestCount++; - * }, - * onComplete: function() { - * Ajax.activeRequestCount--; - * } - * }); - * - * ##### Responder callbacks - * - * The callbacks for responders are similar to the callbacks described in - * the [[Ajax section]], but take a different signature. They're invoked with - * three parameters: the requester object (i.e., the corresponding "instance" - * of [[Ajax.Request]]), the `XMLHttpRequest` object, and the result of - * evaluating the `X-JSON` response header, if any (can be `null`). They also - * execute in the context of the responder, bound to the `this` reference. - * - * * `onCreate`: Triggered whenever a requester object from the `Ajax` - * namespace is created, after its parameters are adjusted and before its - * XHR connection is opened. This takes *two* arguments: the requester - * object and the underlying XHR object. - * * `onUninitialized` (*Not guaranteed*): Invoked just after the XHR object - * is created. - * * `onLoading` (*Not guaranteed*): Triggered when the underlying XHR object - * is being setup, and its connection opened. - * * `onLoaded` (*Not guaranteed*): Triggered once the underlying XHR object - * is setup, the connection is open, and it is ready to send its actual - * request. - * * `onInteractive` (*Not guaranteed*): Triggered whenever the requester - * receives a part of the response (but not the final part), should it - * be sent in several packets. - * * `onException`: Triggered whenever an XHR error arises. Has a custom - * signature: the first argument is the requester (i.e. an [[Ajax.Request]] - * instance), and the second is the exception object. - * * `onComplete`: Triggered at the _very end_ of a request's life-cycle, after - * the request completes, status-specific callbacks are called, and possible - * automatic behaviors are processed. Guaranteed to run regardless of what - * happened during the request. -**/ - -Ajax.Responders = { - responders: [], - - _each: function(iterator, context) { - this.responders._each(iterator, context); - }, - - /** - * Ajax.Responders.register(responder) -> undefined - * - responder (Object): A list of functions with keys corresponding to the - * names of possible callbacks. - * - * Add a group of responders to all Ajax requests. - **/ - register: function(responder) { - if (!this.include(responder)) - this.responders.push(responder); - }, - - /** - * Ajax.Responders.unregister(responder) -> undefined - * - responder (Object): A list of functions with keys corresponding to the - * names of possible callbacks. - * - * Remove a previously-added group of responders. - * - * As always, unregistering something requires you to use the very same - * object you used at registration. If you plan to use `unregister`, be sure - * to assign your responder to a _variable_ before passing it into - * [[Ajax.Responders#register]] — don't pass it an object literal. - **/ - unregister: function(responder) { - this.responders = this.responders.without(responder); - }, - - dispatch: function(callback, request, transport, json) { - this.each(function(responder) { - if (Object.isFunction(responder[callback])) { - try { - responder[callback].apply(responder, [request, transport, json]); - } catch (e) { } - } - }); - } -}; - -Object.extend(Ajax.Responders, Enumerable); - -Ajax.Responders.register({ - onCreate: function() { Ajax.activeRequestCount++ }, - onComplete: function() { Ajax.activeRequestCount-- } -}); diff --git a/src/prototype/ajax/response.js b/src/prototype/ajax/response.js deleted file mode 100644 index c7b53bc04..000000000 --- a/src/prototype/ajax/response.js +++ /dev/null @@ -1,192 +0,0 @@ -/** section: Ajax - * class Ajax.Response - * - * A wrapper class around `XmlHttpRequest` for dealing with HTTP responses - * of Ajax requests. - * - * An instance of [[Ajax.Response]] is passed as the first argument of all Ajax - * requests' callbacks. You _will not_ need to create instances of - * [[Ajax.Response]] yourself. -**/ - -/** - * Ajax.Response#readyState -> Number - * - * A [[Number]] corresponding to the request's current state. - * - * `0` : `"Uninitialized"`
    - * `1` : `"Loading"`
    - * `2` : `"Loaded"`
    - * `3` : `"Interactive"`
    - * `4` : `"Complete"` -**/ - -/** - * Ajax.Response#responseText -> String - * - * The text body of the response. -**/ - -/** - * Ajax.Response#responseXML -> document | null - * - * The XML body of the response if the `Content-type` of the request is set - * to `application/xml`; `null` otherwise. -**/ - -/** - * Ajax.Response#responseJSON -> Object | Array | null - * - * The JSON body of the response if the `Content-type` of the request is set - * to `application/json`; `null` otherwise. -**/ - -/** - * Ajax.Response#headerJSON -> Object | Array | null - * - * Auto-evaluated content of the `X-JSON` header if present; `null` otherwise. - * This is useful to transfer _small_ amounts of data. -**/ - -/** - * Ajax.Response#request -> Ajax.Request | Ajax.Updater - * - * The request object itself (an instance of [[Ajax.Request]] or - * [[Ajax.Updater]]). -**/ - -/** - * Ajax.Response#transport -> XmlHttpRequest - * - * The native `XmlHttpRequest` object itself. -**/ - -Ajax.Response = Class.create({ - // Don't document the constructor; should never be manually instantiated. - initialize: function(request){ - this.request = request; - var transport = this.transport = request.transport, - readyState = this.readyState = transport.readyState; - - if ((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) { - this.status = this.getStatus(); - this.statusText = this.getStatusText(); - this.responseText = String.interpret(transport.responseText); - this.headerJSON = this._getHeaderJSON(); - } - - if (readyState == 4) { - var xml = transport.responseXML; - this.responseXML = Object.isUndefined(xml) ? null : xml; - this.responseJSON = this._getResponseJSON(); - } - }, - - /** - * Ajax.Response#status -> Number - * - * The HTTP status code sent by the server. - **/ - status: 0, - - /** - * Ajax.Response#statusText -> String - * - * The HTTP status text sent by the server. - **/ - statusText: '', - - getStatus: Ajax.Request.prototype.getStatus, - - getStatusText: function() { - try { - return this.transport.statusText || ''; - } catch (e) { return '' } - }, - - /** - * Ajax.Response#getHeader(name) -> String | null - * - * See [[Ajax.Request#getHeader]]. - **/ - getHeader: Ajax.Request.prototype.getHeader, - - /** - * Ajax.Response#getAllHeaders() -> String | null - * - * Returns a [[String]] containing all headers separated by line breaks. - * _Does not_ throw errors if no headers are present the way its native - * counterpart does. - **/ - getAllHeaders: function() { - try { - return this.getAllResponseHeaders(); - } catch (e) { return null } - }, - - /** - * Ajax.Response#getResponseHeader(name) -> String - * - * Returns the value of the requested header if present; throws an error - * otherwise. This is just a wrapper around the `XmlHttpRequest` method of - * the same name. Prefer it's shorter counterpart: - * [[Ajax.Response#getHeader]]. - **/ - getResponseHeader: function(name) { - return this.transport.getResponseHeader(name); - }, - - /** - * Ajax.Response#getAllResponseHeaders() -> String - * - * Returns a [[String]] containing all headers separated by line breaks; throws - * an error if no headers exist. This is just a wrapper around the - * `XmlHttpRequest` method of the same name. Prefer it's shorter counterpart: - * [[Ajax.Response#getAllHeaders]]. - **/ - getAllResponseHeaders: function() { - return this.transport.getAllResponseHeaders(); - }, - - _getHeaderJSON: function() { - var json = this.getHeader('X-JSON'); - if (!json) return null; - - try { - // Browsers expect HTTP headers to be ASCII and nothing else. Running - // them through `decodeURIComponent` processes them with the page's - // specified encoding. - json = decodeURIComponent(escape(json)); - } catch(e) { - // Except Chrome doesn't seem to need this, and calling - // `decodeURIComponent` on text that's already in the proper encoding - // will throw a `URIError`. The ugly solution is to assume that a - // `URIError` raised here signifies that the text is, in fact, already - // in the correct encoding, and treat the failure as a good sign. - // - // This is ugly, but so too is sending extended characters in an HTTP - // header with no spec to back you up. - } - - try { - return json.evalJSON(this.request.options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - }, - - _getResponseJSON: function() { - var options = this.request.options; - if (!options.evalJSON || (options.evalJSON != 'force' && - !(this.getHeader('Content-type') || '').include('application/json')) || - this.responseText.blank()) - return null; - try { - return this.responseText.evalJSON(options.sanitizeJSON || - !this.request.isSameOrigin()); - } catch (e) { - this.request.dispatchException(e); - } - } -}); diff --git a/src/prototype/ajax/updater.js b/src/prototype/ajax/updater.js deleted file mode 100644 index b69b78f79..000000000 --- a/src/prototype/ajax/updater.js +++ /dev/null @@ -1,127 +0,0 @@ -/** section: Ajax - * class Ajax.Updater < Ajax.Request - * - * A class that performs an Ajax request and updates a container's contents - * with the contents of the response. - * - * [[Ajax.Updater]] is a subclass of [[Ajax.Request]] built for a common - * use-case. - * - * ##### Example - * - * new Ajax.Updater('items', '/items', { - * parameters: { text: $F('text') } - * }); - * - * This example will make a request to the URL `/items` (with the given - * parameters); it will then replace the contents of the element with the ID - * of `items` with whatever response it receives. - * - * ##### Callbacks - * - * [[Ajax.Updater]] supports all the callbacks listed in the [[Ajax section]]. - * Note that the `onComplete` callback will be invoked **after** the element - * is updated. - * - * ##### Additional options - * - * [[Ajax.Updater]] has some options of its own apart from the common options - * described in the [[Ajax section]]: - * - * * `evalScripts` ([[Boolean]]; defaults to `false`): Whether `'); - * // -> Element (and prints "updated!" in an alert dialog). - * $('fruits').innerHTML; - * // -> '

    Kiwi, banana and apple.

    ' - * - * Relying on the `toString()` method: - * - * $('fruits').update(123); - * // -> Element - * $('fruits').innerHTML; - * // -> '123' - * - * Finally, you can do some pretty funky stuff by defining your own - * `toString()` method on your custom objects: - * - * var Fruit = Class.create({ - * initialize: function(fruit){ - * this.fruit = fruit; - * }, - * toString: function(){ - * return 'I am a fruit and my name is "' + this.fruit + '".'; - * } - * }); - * var apple = new Fruit('apple'); - * - * $('fruits').update(apple); - * $('fruits').innerHTML; - * // -> 'I am a fruit and my name is "apple".' - **/ - function update(element, content) { - element = $(element); - - // Purge the element's existing contents of all storage keys and - // event listeners, since said content will be replaced no matter - // what. - var descendants = element.getElementsByTagName('*'), - i = descendants.length; - while (i--) purgeElement(descendants[i]); - - if (content && content.toElement) - content = content.toElement(); - - if (Object.isElement(content)) - return element.update().insert(content); - - - content = Object.toHTML(content); - var tagName = element.tagName.toUpperCase(); - - if (ANY_INNERHTML_BUGGY) { - if (tagName in INSERTION_TRANSLATIONS.tags) { - while (element.firstChild) - element.removeChild(element.firstChild); - - var nodes = getContentFromAnonymousElement(tagName, content.stripScripts()); - for (var i = 0, node; node = nodes[i]; i++) - element.appendChild(node); - - } else { - element.innerHTML = content.stripScripts(); - } - } else { - element.innerHTML = content.stripScripts(); - } - - content.evalScripts.bind(content).defer(); - return element; - } - - /** - * Element.replace(@element[, newContent]) -> Element - * - * Replaces `element` _itself_ with `newContent` and returns `element`. - * - * Keep in mind that this method returns the element that has just been - * removed — not the element that took its place. - * - * `newContent` can be either plain text, an HTML snippet or any JavaScript - * object which has a `toString()` method. - * - * If `newContent` contains any `'); - * // -> Element (ul#favorite) and prints "removed!" in an alert dialog. - * - * $('fruits').innerHTML; - * // -> '

    Melon, oranges and grapes.

    ' - * - * With plain text: - * - * $('still-first').replace('Melon, oranges and grapes.'); - * // -> Element (p#still-first) - * - * $('fruits').innerHTML; - * // -> 'Melon, oranges and grapes.' - * - * Finally, relying on the `toString()` method: - * - * $('fruits').replace(123); - * // -> Element - * - * $('food').innerHTML; - * // -> '123' - * - * ##### Warning - * - * Using [[Element.replace]] as an instance method (e.g., - * `$('foo').replace('

    Bar

    ')`) causes errors in Opera 9 when used on - * `input` elements. The `replace` property is reserved on `input` elements - * as part of [Web Forms 2](http://www.whatwg.org/specs/web-forms/current-work/). - * As a workaround, use the generic version instead - * (`Element.replace('foo', '

    Bar

    ')`). - * - **/ - function replace(element, content) { - element = $(element); - - if (content && content.toElement) { - content = content.toElement(); - } else if (!Object.isElement(content)) { - content = Object.toHTML(content); - var range = element.ownerDocument.createRange(); - range.selectNode(element); - content.evalScripts.bind(content).defer(); - content = range.createContextualFragment(content.stripScripts()); - } - - element.parentNode.replaceChild(content, element); - return element; - } - - var INSERTION_TRANSLATIONS = { - before: function(element, node) { - element.parentNode.insertBefore(node, element); - }, - top: function(element, node) { - element.insertBefore(node, element.firstChild); - }, - bottom: function(element, node) { - element.appendChild(node); - }, - after: function(element, node) { - element.parentNode.insertBefore(node, element.nextSibling); - }, - - tags: { - TABLE: ['', '
    ', 1], - TBODY: ['', '
    ', 2], - TR: ['', '
    ', 3], - TD: ['
    ', '
    ', 4], - SELECT: ['', 1] - } - }; - - var tags = INSERTION_TRANSLATIONS.tags; - - Object.extend(tags, { - THEAD: tags.TBODY, - TFOOT: tags.TBODY, - TH: tags.TD - }); - - function replace_IE(element, content) { - element = $(element); - if (content && content.toElement) - content = content.toElement(); - if (Object.isElement(content)) { - element.parentNode.replaceChild(content, element); - return element; - } - - content = Object.toHTML(content); - var parent = element.parentNode, tagName = parent.tagName.toUpperCase(); - - if (tagName in INSERTION_TRANSLATIONS.tags) { - var nextSibling = Element.next(element); - var fragments = getContentFromAnonymousElement( - tagName, content.stripScripts()); - - parent.removeChild(element); - - var iterator; - if (nextSibling) - iterator = function(node) { parent.insertBefore(node, nextSibling) }; - else - iterator = function(node) { parent.appendChild(node); } - - fragments.each(iterator); - } else { - // We don't need to special-case this one. - element.outerHTML = content.stripScripts(); - } - - content.evalScripts.bind(content).defer(); - return element; - } - - if ('outerHTML' in document.documentElement) - replace = replace_IE; - - function isContent(content) { - if (Object.isUndefined(content) || content === null) return false; - - if (Object.isString(content) || Object.isNumber(content)) return true; - if (Object.isElement(content)) return true; - if (content.toElement || content.toHTML) return true; - - return false; - } - - // This private method does the bulk of the work for Element#insert. The - // actual insert method handles argument normalization and multiple - // content insertions. - function insertContentAt(element, content, position) { - position = position.toLowerCase(); - var method = INSERTION_TRANSLATIONS[position]; - - if (content && content.toElement) content = content.toElement(); - if (Object.isElement(content)) { - method(element, content); - return element; - } - - content = Object.toHTML(content); - var tagName = ((position === 'before' || position === 'after') ? - element.parentNode : element).tagName.toUpperCase(); - - var childNodes = getContentFromAnonymousElement(tagName, content.stripScripts()); - - if (position === 'top' || position === 'after') childNodes.reverse(); - - for (var i = 0, node; node = childNodes[i]; i++) - method(element, node); - - content.evalScripts.bind(content).defer(); - } - - /** - * Element.insert(@element, content) -> Element - * - content (String | Element | Object): The content to insert. - * - * Inserts content `above`, `below`, at the `top`, and/or at the `bottom` of - * the given element, depending on the option(s) given. - * - * `insert` accepts content in any of these forms: - * - [[String]]: A string of HTML to be parsed and rendered - * - [[Element]]: An Element instance to insert - * - ...any object with a `toElement` method: The method is called and the resulting element used - * - ...any object with a `toHTML` method: The method is called and the resulting HTML string - * is parsed and rendered - * - * The `content` argument can be the content to insert, in which case the - * implied insertion point is `bottom`, or an object that specifies one or - * more insertion points (e.g., `{ bottom: "foo", top: "bar" }`). - * - * Accepted insertion points are: - * - `before` (as `element`'s previous sibling) - * - `after` (as `element's` next sibling) - * - `top` (as `element`'s first child) - * - `bottom` (as `element`'s last child) - * - * Note that if the inserted HTML contains any ` - **/ - present: function(element) { - return $(element).value != ''; - }, - - /** - * Form.Element.activate(@element) -> Element - * - * Gives focus to a form control and selects its contents if it is a text - * input. - * - * This method is just a shortcut for focusing and selecting; therefore, - * these are equivalent (aside from the fact that the former one will __not__ - * return the field) : - * - * Form.Element.focus('myelement').select() - * $('myelement').activate() - * - * Guess which call is the nicest? ;) - **/ - activate: function(element) { - element = $(element); - try { - element.focus(); - if (element.select && (element.tagName.toLowerCase() != 'input' || - !(/^(?:button|reset|submit)$/i.test(element.type)))) - element.select(); - } catch (e) { } - return element; - }, - - /** - * Form.Element.disable(@element) -> Element - * - * Disables a form control, effectively preventing its value from changing - * until it is enabled again. - * - * This method sets the native `disabled` property of an element to `true`. - * You can use this property to check the state of a control. - * - * ##### Notes - * - * Disabled form controls are never serialized. - * - * Never disable a form control as a security measure without having - * validation for it server-side. A user with minimal experience of - * JavaScript can enable these fields on your site easily using any browser. - * Instead, use disabling as a usability enhancement - with it you can - * indicate that a specific value should not be changed at the time being. - **/ - disable: function(element) { - element = $(element); - element.disabled = true; - return element; - }, - - /** - * Form.Element.enable(@element) -> Element - * - * Enables a previously disabled form control. - **/ - enable: function(element) { - element = $(element); - element.disabled = false; - return element; - } -}; - -/*--------------------------------------------------------------------------*/ - -var Field = Form.Element; - -/** section: DOM, related to: Form - * $F(element) -> String | Array - * - * Returns the value of a form control. This is a convenience alias of - * [[Form.Element.getValue]]. Refer to it for full details. -**/ -var $F = Form.Element.Methods.getValue; - -/*--------------------------------------------------------------------------*/ - -Form.Element.Serializers = (function() { - function input(element, value) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - return inputSelector(element, value); - default: - return valueSelector(element, value); - } - } - - function inputSelector(element, value) { - if (Object.isUndefined(value)) - return element.checked ? element.value : null; - else element.checked = !!value; - } - - function valueSelector(element, value) { - if (Object.isUndefined(value)) return element.value; - else element.value = value; - } - - function select(element, value) { - if (Object.isUndefined(value)) - return (element.type === 'select-one' ? selectOne : selectMany)(element); - - var opt, currentValue, single = !Object.isArray(value); - for (var i = 0, length = element.length; i < length; i++) { - opt = element.options[i]; - currentValue = this.optionValue(opt); - if (single) { - if (currentValue == value) { - opt.selected = true; - return; - } - } - else opt.selected = value.include(currentValue); - } - } - - function selectOne(element) { - var index = element.selectedIndex; - return index >= 0 ? optionValue(element.options[index]) : null; - } - - function selectMany(element) { - var values, length = element.length; - if (!length) return null; - - for (var i = 0, values = []; i < length; i++) { - var opt = element.options[i]; - if (opt.selected) values.push(optionValue(opt)); - } - return values; - } - - function optionValue(opt) { - return Element.hasAttribute(opt, 'value') ? opt.value : opt.text; - } - - return { - input: input, - inputSelector: inputSelector, - textarea: valueSelector, - select: select, - selectOne: selectOne, - selectMany: selectMany, - optionValue: optionValue, - button: valueSelector - }; -})(); - -/*--------------------------------------------------------------------------*/ - -/** section: DOM - * Abstract -**/ - -/** - * class Abstract.TimedObserver - * - * An abstract DOM element observer class, subclasses of which can be used to - * periodically check a value and trigger a callback when the value has changed. - * - * A `TimedObserver` object will try to check a value using the `getValue()` - * instance method which must be defined by the subclass. There are two - * out-of-the-box subclasses: - * [[Form.Observer]], which serializes a form and triggers when the result has - * changed; and [[Form.Element.Observer]], which triggers when the value of a - * given form field changes. - * - * - * Using `TimedObserver` implementations is straightforward; simply instantiate - * them with appropriate arguments. For example: - * - * new Form.Element.Observer( - * 'myelement', - * 0.2, // 200 milliseconds - * function(el, value){ - * alert('The form control has changed value to: ' + value) - * } - * ) - * - * Now that we have instantiated an object, it will check the value of the form - * control every 0.2 seconds and alert us of any change. While it is useless to - * alert the user of his own input (like in the example), we could be doing - * something useful like updating a certain part of the UI or informing the - * application on server of stuff happening (over Ajax). - * - * The callback function is always called with 2 arguments: the element given - * when the observer instance was made and the actual value that has changed - * and caused the callback to be triggered in the first place. - * - * ##### Creating Your Own TimedObserver Implementations - * - * It's easy to create your own `TimedObserver` implementations: Simply subclass - * `TimedObserver` and provide the `getValue()` method. For example, this is the - * complete source code for [[Form.Element.Observer]]: - * - * Form.Element.Observer = Class.create(Abstract.TimedObserver, { - * getValue: function() { - * return Form.Element.getValue(this.element); - * } - * }); -**/ -Abstract.TimedObserver = Class.create(PeriodicalExecuter, { - /** - * new Abstract.TimedObserver(element, frequency, callback) - * - element (String | Element): The DOM element to watch. Can be an element - * instance or an ID. - * - frequency (Number): The frequency, in seconds — e.g., 0.33 to - * check for changes every third of a second. - * - callback (Function): The callback to trigger when the value changes. - * - * Initializes an [[Abstract.TimedObserver]]; used by subclasses. - **/ - initialize: function($super, element, frequency, callback) { - $super(callback, frequency); - this.element = $(element); - this.lastValue = this.getValue(); - }, - - execute: function() { - var value = this.getValue(); - if (Object.isString(this.lastValue) && Object.isString(value) ? - this.lastValue != value : String(this.lastValue) != String(value)) { - this.callback(this.element, value); - this.lastValue = value; - } - } -}); - -/** - * class Form.Element.Observer < Abstract.TimedObserver - * - * An [[Abstract.TimedObserver]] subclass that watches for changes to a form - * field's value. This triggers the callback when the form field's value - * (according to [[Form.Element.getValue]]) changes. (Note that when the value - * actually changes can vary from browser to browser, particularly with - * `select` boxes.) - * - * Form.Element observer implements the `getValue()` method using - * [[Form.Element.getValue]] on the given element. See [[Abstract.TimedObserver]] - * for general documentation on timed observers. -**/ -Form.Element.Observer = Class.create(Abstract.TimedObserver, { - /** - * new Form.Element.Observer(element, frequency, callback) - * - element (String | Element): The form element to watch. Can be an element instance or an ID. - * - frequency (Number): The frequency, in seconds — e.g., 0.33 to check for changes every - * third of a second. - * - callback (Function): The callback to trigger when the value changes. - * - * Creates a [[Form.Element.Observer]]. - **/ - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -/** - * class Form.Observer < Abstract.TimedObserver - * - * An [[Abstract.TimedObserver]] subclass that watches for changes to a form. - * The callback is triggered when the form changes — e.g., when any - * of its fields' values changes, when fields are added/removed, etc.; anything - * that affects the serialized form of the form (see [[Form#serialize]]). - * - * ##### Example - * - * In this example an `observer` is used to change the appearance of the form - * if any of the values had been changed. It returns to its initial state when - * the data is submitted (saved). - * - * language: html - *
    - *
    - * Login Preferences - *

    Current settings:

    - *

    - * - * - *

    - *

    Login options

    - *

    - * - * - *

    - *

    - * - * - *

    - * - *
    - *
    - * - * -**/ -Form.Observer = Class.create(Abstract.TimedObserver, { - /** - * new Form.Observer(element, frequency, callback) - * - element (String | Element): The element of the form to watch. Can be an element - * instance or an ID. - * - frequency (Number): The frequency, in seconds -- e.g., 0.33 to check for changes every - * third of a second. - * - callback (Function): The callback to trigger when the form changes. - * - * Creates a [[Form.Observer]]. - **/ - getValue: function() { - return Form.serialize(this.element); - } -}); - -/*--------------------------------------------------------------------------*/ - -/** - * class Abstract.EventObserver -**/ -Abstract.EventObserver = Class.create({ - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; - - this.lastValue = this.getValue(); - if (this.element.tagName.toLowerCase() == 'form') - this.registerFormCallbacks(); - else - this.registerCallback(this.element); - }, - - onElementEvent: function() { - var value = this.getValue(); - if (this.lastValue != value) { - this.callback(this.element, value); - this.lastValue = value; - } - }, - - registerFormCallbacks: function() { - Form.getElements(this.element).each(this.registerCallback, this); - }, - - registerCallback: function(element) { - if (element.type) { - switch (element.type.toLowerCase()) { - case 'checkbox': - case 'radio': - Event.observe(element, 'click', this.onElementEvent.bind(this)); - break; - default: - Event.observe(element, 'change', this.onElementEvent.bind(this)); - break; - } - } - } -}); - -/** - * class Form.Element.EventObserver < Abstract.EventObserver -**/ -Form.Element.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.Element.getValue(this.element); - } -}); - -/** - * class Form.EventObserver < Abstract.EventObserver -**/ -Form.EventObserver = Class.create(Abstract.EventObserver, { - getValue: function() { - return Form.serialize(this.element); - } -}); diff --git a/src/prototype/dom/layout.js b/src/prototype/dom/layout.js deleted file mode 100644 index 89a4057c8..000000000 --- a/src/prototype/dom/layout.js +++ /dev/null @@ -1,1614 +0,0 @@ -(function() { - - // Converts a CSS percentage value to a decimal. - // Ex: toDecimal("30%"); // -> 0.3 - function toDecimal(pctString) { - var match = pctString.match(/^(\d+)%?$/i); - if (!match) return null; - return (Number(match[1]) / 100); - } - - // A bare-bones version of Element.getStyle. Needed because getStyle is - // public-facing and too user-friendly for our tastes. We need raw, - // non-normalized values. - // - // Camel-cased property names only. - function getRawStyle(element, style) { - element = $(element); - - // Try inline styles first. - var value = element.style[style]; - if (!value || value === 'auto') { - // Reluctantly retrieve the computed style. - 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; - } - - // Quickly figures out the content width of an element. Used instead of - // `element.measure('width')` in several places below; we don't want to - // call back into layout code recursively if we don't have to. - // - // But this means it doesn't handle edge cases. Use it when you know the - // element in question is visible and will give accurate measurements. - function getContentWidth(element, context) { - var boxWidth = element.offsetWidth; - - var bl = getPixelValue(element, 'borderLeftWidth', context) || 0; - var br = getPixelValue(element, 'borderRightWidth', context) || 0; - var pl = getPixelValue(element, 'paddingLeft', context) || 0; - var pr = getPixelValue(element, 'paddingRight', context) || 0; - - return boxWidth - bl - br - pl - pr; - } - - // Can be called like this: - // getPixelValue("11px"); - // Or like this: - // getPixelValue(someElement, 'paddingTop'); - function getPixelValue(value, property, context) { - var element = null; - if (Object.isElement(value)) { - element = value; - value = getRawStyle(element, property); - } - - if (value === null || Object.isUndefined(value)) { - return null; - } - - // Non-IE browsers will always return pixels if possible. - // (We use parseFloat instead of parseInt because Firefox can return - // non-integer pixel values.) - if ((/^(?:-)?\d+(\.\d+)?(px)?$/i).test(value)) { - return window.parseFloat(value); - } - - var isPercentage = value.include('%'); - - // For other browsers, we have to do a bit of work. - // (At this point, only percentages should be left; all other CSS units - // are converted to pixels by getComputedStyle.) - if (element && isPercentage) { - // The `context` argument comes into play for percentage units; it's - // the thing that the unit represents a percentage of. When an - // absolutely-positioned element has a width of 50%, we know that's - // 50% of its offset parent. If it's `position: fixed` instead, we know - // it's 50% of the viewport. And so on. - context = context || element.parentNode; - var decimal = toDecimal(value), whole = null; - - var isHorizontal = property.include('left') || property.include('right') || - property.include('width'); - - var isVertical = property.include('top') || property.include('bottom') || - property.include('height'); - - if (context === document.viewport) { - if (isHorizontal) { - whole = document.viewport.getWidth(); - } else if (isVertical) { - whole = document.viewport.getHeight(); - } - } else { - if (isHorizontal) { - whole = $(context).measure('width'); - } else if (isVertical) { - whole = $(context).measure('height'); - } - } - - return (whole === null) ? 0 : whole * decimal; - } - - // If we get this far, we should probably give up. - return 0; - } - - // Shortcut for figuring out if an element is `display: none` or not. - function isDisplayed(element) { - while (element && element.parentNode) { - var display = element.getStyle('display'); - if (display === 'none') { - return false; - } - element = element.parentNode; - } - return true; - } - - // Converts the layout hash property names back to the CSS equivalents. - // For now, only the border properties differ. - function cssNameFor(key) { - if (key.include('border')) key = key + '-width'; - return key.camelize(); - } - - /** - * class Element.Layout < Hash - * - * A set of key/value pairs representing measurements of various - * dimensions of an element. - * - *

    Overview

    - * - * The `Element.Layout` class is a specialized way to measure elements. - * It helps mitigate: - * - * * The convoluted steps often needed to get common measurements for - * elements. - * * The tendency of browsers to report measurements in non-pixel units. - * * The quirks that lead some browsers to report inaccurate measurements. - * * The difficulty of measuring elements that are hidden. - * - *

    Usage

    - * - * Instantiate an `Element.Layout` class by passing an element into the - * constructor: - * - * var layout = new Element.Layout(someElement); - * - * You can also use [[Element.getLayout]], if you prefer. - * - * Once you have a layout object, retrieve properties using [[Hash]]'s - * familiar `get` and `set` syntax. - * - * layout.get('width'); //-> 400 - * layout.get('top'); //-> 180 - * - * The following are the CSS-related properties that can be retrieved. - * Nearly all of them map directly to their property names in CSS. (The - * only exception is for borders — e.g., `border-left` instead of - * `border-left-width`.) - * - * * `height` - * * `width` - * * `top` - * * `left` - * * `right` - * * `bottom` - * * `border-left` - * * `border-right` - * * `border-top` - * * `border-bottom` - * * `padding-left` - * * `padding-right` - * * `padding-top` - * * `padding-bottom` - * * `margin-top` - * * `margin-bottom` - * * `margin-left` - * * `margin-right` - * - * In addition, these "composite" properties can be retrieved: - * - * * `padding-box-width` (width of the content area, from the beginning of - * the left padding to the end of the right padding) - * * `padding-box-height` (height of the content area, from the beginning - * of the top padding to the end of the bottom padding) - * * `border-box-width` (width of the content area, from the outer edge of - * the left border to the outer edge of the right border) - * * `border-box-height` (height of the content area, from the outer edge - * of the top border to the outer edge of the bottom border) - * * `margin-box-width` (width of the content area, from the beginning of - * the left margin to the end of the right margin) - * * `margin-box-height` (height of the content area, from the beginning - * of the top margin to the end of the bottom margin) - * - *

    Caching

    - * - * Because these properties can be costly to retrieve, `Element.Layout` - * behaves differently from an ordinary [[Hash]]. - * - * First: by default, values are "lazy-loaded" — they aren't computed - * until they're retrieved. To measure all properties at once, pass - * a second argument into the constructor: - * - * var layout = new Element.Layout(someElement, true); - * - * Second: once a particular value is computed, it's cached. Asking for - * the same property again will return the original value without - * re-computation. This means that **an instance of `Element.Layout` - * becomes stale when the element's dimensions change**. When this - * happens, obtain a new instance. - * - *

    Hidden elements

    - * - * Because it's a common case to want the dimensions of a hidden element - * (e.g., for animations), it's possible to measure elements that are - * hidden with `display: none`. - * - * However, **it's only possible to measure a hidden element if its parent - * is visible**. If its parent (or any other ancestor) is hidden, any - * width and height measurements will return `0`, as will measurements for - * `top|bottom|left|right`. - * - **/ - Element.Layout = Class.create(Hash, { - /** - * new Element.Layout(element[, preCompute = false]) - * - element (Element): The element to be measured. - * - preCompute (Boolean): Whether to compute all values at once. Default - * is `false`. - * - * Declare a new layout hash. - * - * The `preCompute` argument determines whether measurements will be - * lazy-loaded or not. If you plan to use many different measurements, - * it's often more performant to pre-compute, as it minimizes the - * amount of overhead needed to measure. If you need only one or two - * measurements, it's probably not worth it. - **/ - initialize: function($super, element, preCompute) { - $super(); - this.element = $(element); - - // nullify all properties keys - Element.Layout.PROPERTIES.each( function(property) { - this._set(property, null); - }, this); - - // The 'preCompute' boolean tells us whether we should fetch all values - // at once. If so, we should do setup/teardown only once. We set a flag - // so that we can ignore calls to `_begin` and `_end` elsewhere. - if (preCompute) { - this._preComputing = true; - this._begin(); - Element.Layout.PROPERTIES.each( this._compute, this ); - this._end(); - this._preComputing = false; - } - }, - - _set: function(property, value) { - return Hash.prototype.set.call(this, property, value); - }, - - // TODO: Investigate. - set: function(property, value) { - throw "Properties of Element.Layout are read-only."; - }, - - /** - * Element.Layout#get(property) -> Number - * - property (String): One of the properties defined in - * [[Element.Layout.PROPERTIES]]. - * - * Retrieve the measurement specified by `property`. Will throw an error - * if the property is invalid. - * - * ##### Caveats - * - * * `Element.Layout` can measure the dimensions of an element hidden with - * CSS (`display: none`), but _only_ if its parent element is visible. - **/ - get: function($super, property) { - // Try to fetch from the cache. - var value = $super(property); - return value === null ? this._compute(property) : value; - }, - - // `_begin` and `_end` are two functions that are called internally - // before and after any measurement is done. In certain conditions (e.g., - // when hidden), elements need a "preparation" phase that ensures - // accuracy of measurements. - _begin: function() { - if (this._isPrepared()) return; - - var element = this.element; - if (isDisplayed(element)) { - this._setPrepared(true); - return; - } - - // If we get this far, it means this element is hidden. To get usable - // measurements, we must remove `display: none`, but in a manner that - // isn't noticeable to the user. That means we also set - // `visibility: hidden` to make it invisible, and `position: absolute` - // so that it won't alter the document flow when displayed. - // - // Once we do this, the element is "prepared," and we can make our - // measurements. When we're done, the `_end` method cleans up our - // changes. - - // Remember the original values for some styles we're going to alter. - var originalStyles = { - position: element.style.position || '', - width: element.style.width || '', - visibility: element.style.visibility || '', - display: element.style.display || '' - }; - - // We store them so that the `_end` method can retrieve them later. - element.store('prototype_original_styles', originalStyles); - - var position = getRawStyle(element, 'position'), width = element.offsetWidth; - - if (width === 0 || width === null) { - // Opera/IE won't report the true width of the element through - // `getComputedStyle` if it's hidden. If we got a nonsensical value, - // we need to show the element and try again. - element.style.display = 'block'; - width = element.offsetWidth; - } - - // Preserve the context in case we get a percentage value. - var context = (position === 'fixed') ? document.viewport : - element.parentNode; - - var tempStyles = { - visibility: 'hidden', - display: 'block' - }; - - // If the element's `position: fixed`, it's already out of the document - // flow, so it's both unnecessary and inaccurate to set - // `position: absolute`. - if (position !== 'fixed') tempStyles.position = 'absolute'; - - element.setStyle(tempStyles); - - var positionedWidth = element.offsetWidth, newWidth; - if (width && (positionedWidth === width)) { - // If the element's width is the same both before and after - // we set absolute positioning, that means: - // (a) it was already absolutely-positioned; or - // (b) it has an explicitly-set width, instead of width: auto. - // Either way, it means the element is the width it needs to be - // in order to report an accurate height. - newWidth = getContentWidth(element, context); - } else if (position === 'absolute' || position === 'fixed') { - // Absolute- and fixed-position elements' dimensions don't depend - // upon those of their parents. - newWidth = getContentWidth(element, context); - } else { - // Otherwise, the element's width depends upon the width of its - // parent. - var parent = element.parentNode, pLayout = parent.getLayout(); - - newWidth = pLayout.get('width') - - this.get('margin-left') - - this.get('border-left') - - this.get('padding-left') - - this.get('padding-right') - - this.get('border-right') - - this.get('margin-right'); - } - - // Whatever the case, we've now figured out the correct `width` value - // for the element. - element.setStyle({ width: newWidth + 'px' }); - - // The element is now ready for measuring. - this._setPrepared(true); - }, - - _end: function() { - var element = this.element; - var originalStyles = element.retrieve('prototype_original_styles'); - element.store('prototype_original_styles', null); - element.setStyle(originalStyles); - this._setPrepared(false); - }, - - _compute: function(property) { - var COMPUTATIONS = Element.Layout.COMPUTATIONS; - if (!(property in COMPUTATIONS)) { - throw "Property not found."; - } - - return this._set(property, COMPUTATIONS[property].call(this, this.element)); - }, - - _isPrepared: function() { - return this.element.retrieve('prototype_element_layout_prepared', false); - }, - - _setPrepared: function(bool) { - return this.element.store('prototype_element_layout_prepared', bool); - }, - - /** - * Element.Layout#toObject([keys...]) -> Object - * - keys (String): A space-separated list of keys to include. - * - * Converts the layout hash to a plain object of key/value pairs, - * optionally including only the given keys. - * - * Keys can be passed into this method as individual arguments _or_ - * separated by spaces within a string. - * - * // Equivalent statements: - * someLayout.toObject('top', 'bottom', 'left', 'right'); - * someLayout.toObject('top bottom left right'); - **/ - toObject: function() { - var args = $A(arguments); - var keys = (args.length === 0) ? Element.Layout.PROPERTIES : - args.join(' ').split(' '); - var obj = {}; - keys.each( function(key) { - // Key needs to be a valid Element.Layout property. - if (!Element.Layout.PROPERTIES.include(key)) return; - var value = this.get(key); - if (value != null) obj[key] = value; - }, this); - return obj; - }, - - /** - * Element.Layout#toHash([keys...]) -> Hash - * - keys (String): A space-separated list of keys to include. - * - * Converts the layout hash to an ordinary hash of key/value pairs, - * optionally including only the given keys. - * - * Keys can be passed into this method as individual arguments _or_ - * separated by spaces within a string. - * - * // Equivalent statements: - * someLayout.toHash('top', 'bottom', 'left', 'right'); - * someLayout.toHash('top bottom left right'); - **/ - toHash: function() { - var obj = this.toObject.apply(this, arguments); - return new Hash(obj); - }, - - /** - * Element.Layout#toCSS([keys...]) -> Object - * - keys (String): A space-separated list of keys to include. - * - * Converts the layout hash to a plain object of CSS property/value - * pairs, optionally including only the given keys. - * - * Keys can be passed into this method as individual arguments _or_ - * separated by spaces within a string. - * - * // Equivalent statements: - * someLayout.toCSS('top', 'bottom', 'left', 'right'); - * someLayout.toCSS('top bottom left right'); - * - * Useful for passing layout properties to [[Element.setStyle]]. - **/ - toCSS: function() { - var args = $A(arguments); - var keys = (args.length === 0) ? Element.Layout.PROPERTIES : - args.join(' ').split(' '); - var css = {}; - - keys.each( function(key) { - // Key needs to be a valid Element.Layout property... - if (!Element.Layout.PROPERTIES.include(key)) return; - // ...but not a composite property. - if (Element.Layout.COMPOSITE_PROPERTIES.include(key)) return; - - var value = this.get(key); - if (value != null) css[cssNameFor(key)] = value + 'px'; - }, this); - return css; - }, - - inspect: function() { - return "#"; - } - }); - - Object.extend(Element.Layout, { - /** - * Element.Layout.PROPERTIES = Array - * - * A list of all measurable properties. - **/ - PROPERTIES: $w('height width top left right bottom border-left border-right border-top border-bottom padding-left padding-right padding-top padding-bottom margin-top margin-bottom margin-left margin-right padding-box-width padding-box-height border-box-width border-box-height margin-box-width margin-box-height'), - - /** - * Element.Layout.COMPOSITE_PROPERTIES = Array - * - * A list of all composite properties. Composite properties don't map - * directly to CSS properties — they're combinations of other - * properties. - **/ - COMPOSITE_PROPERTIES: $w('padding-box-width padding-box-height margin-box-width margin-box-height border-box-width border-box-height'), - - COMPUTATIONS: { - 'height': function(element) { - if (!this._preComputing) this._begin(); - - var bHeight = this.get('border-box-height'); - if (bHeight <= 0) { - if (!this._preComputing) this._end(); - return 0; - } - - var bTop = this.get('border-top'), - bBottom = this.get('border-bottom'); - - var pTop = this.get('padding-top'), - pBottom = this.get('padding-bottom'); - - if (!this._preComputing) this._end(); - - return bHeight - bTop - bBottom - pTop - pBottom; - }, - - 'width': function(element) { - if (!this._preComputing) this._begin(); - - var bWidth = this.get('border-box-width'); - if (bWidth <= 0) { - if (!this._preComputing) this._end(); - return 0; - } - - var bLeft = this.get('border-left'), - bRight = this.get('border-right'); - - var pLeft = this.get('padding-left'), - pRight = this.get('padding-right'); - - if (!this._preComputing) this._end(); - return bWidth - bLeft - bRight - pLeft - pRight; - }, - - 'padding-box-height': function(element) { - var height = this.get('height'), - pTop = this.get('padding-top'), - pBottom = this.get('padding-bottom'); - - return height + pTop + pBottom; - }, - - 'padding-box-width': function(element) { - var width = this.get('width'), - pLeft = this.get('padding-left'), - pRight = this.get('padding-right'); - - return width + pLeft + pRight; - }, - - 'border-box-height': function(element) { - if (!this._preComputing) this._begin(); - var height = element.offsetHeight; - if (!this._preComputing) this._end(); - return height; - }, - - 'border-box-width': function(element) { - if (!this._preComputing) this._begin(); - var width = element.offsetWidth; - if (!this._preComputing) this._end(); - return width; - }, - - 'margin-box-height': function(element) { - var bHeight = this.get('border-box-height'), - mTop = this.get('margin-top'), - mBottom = this.get('margin-bottom'); - - if (bHeight <= 0) return 0; - - return bHeight + mTop + mBottom; - }, - - 'margin-box-width': function(element) { - var bWidth = this.get('border-box-width'), - mLeft = this.get('margin-left'), - mRight = this.get('margin-right'); - - if (bWidth <= 0) return 0; - - return bWidth + mLeft + mRight; - }, - - 'top': function(element) { - var offset = element.positionedOffset(); - return offset.top; - }, - - 'bottom': function(element) { - var parent = element.getOffsetParent(); - var rect = element.getBoundingClientRect(), - pRect = parent.getBoundingClientRect(); - - return (pRect.bottom - rect.bottom).round(); - }, - - 'left': function(element) { - var offset = element.positionedOffset(); - return offset.left; - }, - - 'right': function(element) { - var parent = element.getOffsetParent(); - var rect = element.getBoundingClientRect(), - pRect = parent.getBoundingClientRect(); - - return (pRect.right - rect.right).round(); - }, - - 'padding-top': function(element) { - return getPixelValue(element, 'paddingTop'); - }, - - 'padding-bottom': function(element) { - return getPixelValue(element, 'paddingBottom'); - }, - - 'padding-left': function(element) { - return getPixelValue(element, 'paddingLeft'); - }, - - 'padding-right': function(element) { - return getPixelValue(element, 'paddingRight'); - }, - - 'border-top': function(element) { - return getPixelValue(element, 'borderTopWidth'); - }, - - 'border-bottom': function(element) { - return getPixelValue(element, 'borderBottomWidth'); - }, - - 'border-left': function(element) { - return getPixelValue(element, 'borderLeftWidth'); - }, - - 'border-right': function(element) { - return getPixelValue(element, 'borderRightWidth'); - }, - - 'margin-top': function(element) { - return getPixelValue(element, 'marginTop'); - }, - - 'margin-bottom': function(element) { - return getPixelValue(element, 'marginBottom'); - }, - - 'margin-left': function(element) { - return getPixelValue(element, 'marginLeft'); - }, - - 'margin-right': function(element) { - return getPixelValue(element, 'marginRight'); - } - } - }); - - /** - * class Element.Offset - * - * A representation of the top- and left-offsets of an element relative to - * another. - * - * All methods that compute offsets return an instance of `Element.Offset`. - * - **/ - Element.Offset = Class.create({ - /** - * new Element.Offset(left, top) - * - * Instantiates an [[Element.Offset]]. You shouldn't need to call this - * directly. - **/ - initialize: function(left, top) { - this.left = left.round(); - this.top = top.round(); - - // Act like an array. - this[0] = this.left; - this[1] = this.top; - }, - - /** - * Element.Offset#relativeTo(offset) -> Element.Offset - * - offset (Element.Offset): Another offset to compare to. - * - * Returns a new [[Element.Offset]] with its origin at the given - * `offset`. Useful for determining an element's distance from another - * arbitrary element. - **/ - relativeTo: function(offset) { - return new Element.Offset( - this.left - offset.left, - this.top - offset.top - ); - }, - - /** - * Element.Offset#inspect() -> String - * - * Returns a debug-friendly representation of the offset. - **/ - inspect: function() { - return "#".interpolate(this); - }, - - /** - * Element.Offset#toString() -> String - **/ - toString: function() { - return "[#{left}, #{top}]".interpolate(this); - }, - - /** - * Element.Offset#toArray() -> Array - * - * Returns an array representation fo the offset in [x, y] format. - **/ - toArray: function() { - return [this.left, this.top]; - } - }); - - /** - * Element.getLayout(@element[, preCompute = false]) -> Element.Layout - * - element (Element): The element to be measured. - * - preCompute (Boolean): Whether to compute all values at once. Default - * is `false`. - * - * Returns an instance of [[Element.Layout]] for measuring an element's - * dimensions. - * - * Note that this method returns a _new_ `Element.Layout` object each time - * it's called. If you want to take advantage of measurement caching, - * retain a reference to one `Element.Layout` object, rather than calling - * `Element.getLayout` whenever you need a measurement. You should call - * `Element.getLayout` again only when the values in an existing - * `Element.Layout` object have become outdated. - * - * If the `preCompute` argument is `true`, all properties will be measured - * when the layout object is instantiated. If you plan to measure several - * properties of an element's dimensions, it's probably worth it to get a - * pre-computed hash. - * - * ##### Examples - * - * var layout = $('troz').getLayout(); - * - * layout.get('width'); //-> 150 - * layout.get('height'); //-> 500 - * layout.get('padding-left'); //-> 10 - * layout.get('margin-left'); //-> 25 - * layout.get('border-top'); //-> 5 - * layout.get('border-bottom'); //-> 5 - * - * // Won't re-compute width; remembers value from first time. - * layout.get('width'); //-> 150 - * - * // Composite values obtained by adding together other properties; - * // will re-use any values we've already looked up above. - * layout.get('padding-box-width'); //-> 170 - * layout.get('border-box-height'); //-> 510 - * - * ##### Caveats - * - * * Instances of `Element.Layout` can measure the dimensions of an - * element hidden with CSS (`display: none`), but _only_ if its parent - * element is visible. - **/ - function getLayout(element, preCompute) { - return new Element.Layout(element, preCompute); - } - - /** - * Element.measure(@element, property) -> Number - * - * Gives the pixel value of `element`'s dimension specified by - * `property`. - * - * Useful for one-off measurements of elements. If you find yourself - * calling this method frequently over short spans of code, you might want - * to call [[Element.getLayout]] and operate on the [[Element.Layout]] - * object itself (thereby taking advantage of measurement caching). - * - * ##### Examples - * - * $('troz').measure('width'); //-> 150 - * $('troz').measure('border-top'); //-> 5 - * $('troz').measure('top'); //-> 226 - * - * ##### Caveats - * - * * `Element.measure` can measure the dimensions of an element hidden with - * CSS (`display: none`), but _only_ if its parent element is visible. - **/ - function measure(element, property) { - return $(element).getLayout().get(property); - } - - /** - * Element.getHeight(@element) -> Number - * - * Returns the height of `element`. - * - * This method returns correct values on elements whose display is set to - * `none` either in an inline style rule or in an CSS stylesheet. - * - * For performance reasons, if you need to query both width _and_ height of - * `element`, you should consider using [[Element.getDimensions]] instead. - * - * Note that the value returned is a _number only_ although it is - * _expressed in pixels_. - * - * ##### Examples - * - * language: html - *
    - * - * Then: - * - * $('rectangle').getHeight(); - * // -> 100 - **/ - function getHeight(element) { - return Element.getDimensions(element).height; - } - - /** - * Element.getWidth(@element) -> Number - * - * Returns the width of `element`. - * - * This method returns correct values on elements whose display is set to - * `none` either in an inline style rule or in an CSS stylesheet. - * - * For performance reasons, if you need to query both width _and_ height of - * `element`, you should consider using [[Element.getDimensions]] instead. - * - * Note that the value returned is a _number only_ although it is - * _expressed in pixels_. - * - * ##### Examples - * - * language: html - *
    - * - * Then: - * - * $('rectangle').getWidth(); - * // -> 200 - **/ - function getWidth(element) { - return Element.getDimensions(element).width; - } - - /** - * Element.getDimensions(@element) -> Object - * - * Finds the computed width and height of `element` and returns them as - * key/value pairs of an object. - * - * For backwards-compatibility, these dimensions represent the dimensions - * of the element's "border box" (including CSS padding and border). This - * is equivalent to the built-in `offsetWidth` and `offsetHeight` - * browser properties. - * - * Note that all values are returned as _numbers only_ although they are - * _expressed in pixels_. - * - * ##### Caveats - * - * * If the element is hidden via `display: none` in CSS, this method will - * attempt to measure the element by temporarily removing that CSS and - * applying `visibility: hidden` and `position: absolute`. This gives - * the element dimensions without making it visible or affecting the - * positioning of surrounding elements — but may not give accurate - * results in some cases. [[Element.measure]] is designed to give more - * accurate results. - * - * * In order to avoid calling the method twice, you should consider - * caching the returned values in a variable, as shown in the example - * below. - * - * * For more complex use cases, use [[Element.measure]], which is able - * to measure many different aspects of an element's dimensions and - * offsets. - * - * ##### Examples - * - * language: html - *
    - * - * Then: - * - * var dimensions = $('rectangle').getDimensions(); - * // -> {width: 200, height: 100} - * - * dimensions.width; - * // -> 200 - * - * dimensions.height; - * // -> 100 - **/ - function getDimensions(element) { - element = $(element); - var display = Element.getStyle(element, 'display'); - - if (display && display !== 'none') { - return { width: element.offsetWidth, height: element.offsetHeight }; - } - - // All *Width and *Height properties give 0 on elements with - // `display: none`, so show the element temporarily. - var style = element.style; - var originalStyles = { - visibility: style.visibility, - position: style.position, - display: style.display - }; - - var newStyles = { - visibility: 'hidden', - display: 'block' - }; - - // Switching `fixed` to `absolute` causes issues in Safari. - if (originalStyles.position !== 'fixed') - newStyles.position = 'absolute'; - - Element.setStyle(element, newStyles); - - var dimensions = { - width: element.offsetWidth, - height: element.offsetHeight - }; - - Element.setStyle(element, originalStyles); - - return dimensions; - } - - /** - * Element.getOffsetParent(@element) -> Element - * - * Returns `element`'s closest _positioned_ ancestor. If none is found, the - * `body` element is returned. - **/ - function getOffsetParent(element) { - element = $(element); - - // Ensure we never return the root HTML tag. - function selfOrBody(element) { - return isHtml(element) ? document.body : $(element); - } - - // For unusual cases like these, we standardize on returning the BODY - // element as the offset parent. - if (isDocument(element) || isDetached(element) || isBody(element) || isHtml(element)) - return document.body; - - // IE reports offset parent incorrectly for inline elements. - var isInline = (Element.getStyle(element, 'display') === 'inline'); - if (!isInline && element.offsetParent) return selfOrBody(element.offsetParent); - - while ((element = element.parentNode) && element !== document.body) { - if (Element.getStyle(element, 'position') !== 'static') { - return selfOrBody(element); - } - } - - return document.body; - } - - - /** - * Element.cumulativeOffset(@element) -> Element.Offset - * - * Returns the offsets of `element` from the top left corner of the - * document. - **/ - function cumulativeOffset(element) { - element = $(element); - var valueT = 0, valueL = 0; - if (element.parentNode) { - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - } while (element); - } - return new Element.Offset(valueL, valueT); - } - - /** - * Element.positionedOffset(@element) -> Element.Offset - * - * Returns `element`'s offset relative to its closest positioned ancestor - * (the element that would be returned by [[Element.getOffsetParent]]). - **/ - function positionedOffset(element) { - element = $(element); - - // Account for the margin of the element. - var layout = element.getLayout(); - - var valueT = 0, valueL = 0; - do { - valueT += element.offsetTop || 0; - valueL += element.offsetLeft || 0; - element = element.offsetParent; - if (element) { - if (isBody(element)) break; - var p = Element.getStyle(element, 'position'); - if (p !== 'static') break; - } - } while (element); - - valueL -= layout.get('margin-left'); - valueT -= layout.get('margin-top'); - - return new Element.Offset(valueL, valueT); - } - - /** - * Element.cumulativeScrollOffset(@element) -> Element.Offset - * - * Calculates the cumulative scroll offset of an element in nested - * scrolling containers. - **/ - function cumulativeScrollOffset(element) { - var valueT = 0, valueL = 0; - do { - if (element === document.body) { - var bodyScrollNode = document.documentElement || document.body.parentNode || document.body; - valueT += !Object.isUndefined(window.pageYOffset) ? window.pageYOffset : bodyScrollNode.scrollTop || 0; - valueL += !Object.isUndefined(window.pageXOffset) ? window.pageXOffset : bodyScrollNode.scrollLeft || 0; - break; - } else { - valueT += element.scrollTop || 0; - valueL += element.scrollLeft || 0; - element = element.parentNode; - } - } while (element); - return new Element.Offset(valueL, valueT); - } - - /** - * Element.viewportOffset(@element) -> Element.Offset - * - * Returns the X/Y coordinates of element relative to the viewport. - **/ - function viewportOffset(element) { - element = $(element); - if (isDetached(element)) return new Element.Offset(0, 0); - - var rect = element.getBoundingClientRect(); - return new Element.Offset(rect.left, rect.top); - } - - /** - * Element.absolutize(@element) -> Element - * - * Turns `element` into an absolutely-positioned element _without_ - * changing its position in the page layout. - **/ - function absolutize(element) { - element = $(element); - - if (Element.getStyle(element, 'position') === 'absolute') { - return element; - } - - var offsetParent = getOffsetParent(element); - var eOffset = element.viewportOffset(), - pOffset = offsetParent.viewportOffset(); - - var offset = eOffset.relativeTo(pOffset); - var layout = element.getLayout(); - - element.store('prototype_absolutize_original_styles', { - position: element.getStyle('position'), - left: element.getStyle('left'), - top: element.getStyle('top'), - width: element.getStyle('width'), - height: element.getStyle('height') - }); - - element.setStyle({ - position: 'absolute', - top: offset.top + 'px', - left: offset.left + 'px', - width: layout.get('width') + 'px', - height: layout.get('height') + 'px' - }); - - return element; - } - - /** - * Element.relativize(@element) -> Element - * - * Turns `element` into a relatively-positioned element without changing - * its position in the page layout. - * - * Used to undo a call to [[Element.absolutize]]. - **/ - function relativize(element) { - element = $(element); - if (Element.getStyle(element, 'position') === 'relative') { - return element; - } - - // Restore the original styles as captured by Element#absolutize. - var originalStyles = - element.retrieve('prototype_absolutize_original_styles'); - - if (originalStyles) element.setStyle(originalStyles); - return element; - } - - - /** - * Element.scrollTo(@element) -> Element - * - * Scrolls the window so that `element` appears at the top of the viewport. - * - * This has a similar effect than what would be achieved using - * [HTML anchors](http://www.w3.org/TR/html401/struct/links.html#h-12.2.3) - * (except the browser's history is not modified). - * - * ##### Example - * - * $(element).scrollTo(); - * // -> Element - **/ - function scrollTo(element) { - element = $(element); - var pos = Element.cumulativeOffset(element); - window.scrollTo(pos.left, pos.top); - return element; - } - - - /** - * Element.makePositioned(@element) -> Element - * - * Allows for the easy creation of a CSS containing block by setting - * `element`'s CSS `position` to `relative` if its initial position is - * either `static` or `undefined`. - * - * To revert back to `element`'s original CSS position, use - * [[Element.undoPositioned]]. - **/ - function makePositioned(element) { - element = $(element); - var position = Element.getStyle(element, 'position'), styles = {}; - if (position === 'static' || !position) { - styles.position = 'relative'; - Element.setStyle(element, styles); - Element.store(element, 'prototype_made_positioned', true); - } - return element; - } - - /** - * Element.undoPositioned(@element) -> Element - * - * Sets `element` back to the state it was in _before_ - * [[Element.makePositioned]] was applied to it. - * - * `element`'s absolutely positioned children will now have their positions - * set relatively to `element`'s nearest ancestor with a CSS `position` of - * `'absolute'`, `'relative'` or `'fixed'`. - **/ - function undoPositioned(element) { - element = $(element); - var storage = Element.getStorage(element), - madePositioned = storage.get('prototype_made_positioned'); - - if (madePositioned) { - storage.unset('prototype_made_positioned'); - Element.setStyle(element, { - position: '', - top: '', - bottom: '', - left: '', - right: '' - }); - } - return element; - } - - /** - * Element.makeClipping(@element) -> Element - * - * Simulates the poorly-supported CSS `clip` property by setting `element`'s - * `overflow` value to `hidden`. - * - * To undo clipping, use [[Element.undoClipping]]. - * - * The visible area is determined by `element`'s width and height. - * - * ##### Example - * - * language:html - *
    - * example - *
    - * - * Then: - * - * $('framer').makeClipping().setStyle({width: '100px', height: '100px'}); - * // -> Element - * - * Another example: - * - * language: html - * Click me to try it out. - * - *
    - * example - *
    - * - * - **/ - function makeClipping(element) { - element = $(element); - - var storage = Element.getStorage(element), - madeClipping = storage.get('prototype_made_clipping'); - - // The "prototype_made_clipping" storage key is meant to hold the - // original CSS overflow value. A string value or `null` means that we've - // called `makeClipping` already. An `undefined` value means we haven't. - if (Object.isUndefined(madeClipping)) { - var overflow = Element.getStyle(element, 'overflow'); - storage.set('prototype_made_clipping', overflow); - if (overflow !== 'hidden') - element.style.overflow = 'hidden'; - } - - return element; - } - - /** - * Element.undoClipping(@element) -> Element - * - * Sets `element`'s CSS `overflow` property back to the value it had - * _before_ [[Element.makeClipping]] was applied. - * - * ##### Example - * - * language: html - *
    - * example - *
    - * - * Then: - * - * $('framer').undoClipping(); - * // -> Element (and sets the CSS overflow property to its original value). - * - * Another example: - * - * language: html - * Click me to try it out. - * - *
    - * example - *
    - * - * - **/ - function undoClipping(element) { - element = $(element); - var storage = Element.getStorage(element), - overflow = storage.get('prototype_made_clipping'); - - if (!Object.isUndefined(overflow)) { - storage.unset('prototype_made_clipping'); - element.style.overflow = overflow || ''; - } - - return element; - } - - /** - * Element.clonePosition(@element, source[, options]) -> Element - * - source (Element | String): The source element (or its ID). - * - options (Object): The position fields to clone. - * - * Clones the position and/or dimensions of `source` onto the element as - * defined by `options`, with an optional offset for the `left` and `top` - * properties. - * - * Note that the element will be positioned exactly like `source` whether or - * not it is part of the same [CSS containing - * block](http://www.w3.org/TR/CSS21/visudet.html#containing-block-details). - * - * Also note that `element` must already be `position: absolute` or - * `position: fixed`. This method will not apply a `position` style. - * - * ##### Options - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    NameDefaultDescription
    setLefttrueClones source's left CSS property onto element.
    setToptrueClones source's top CSS property onto element.
    setWidthtrueClones source's width onto element.
    setHeighttrueClones source's width onto element.
    offsetLeft0Number by which to offset element's left CSS property.
    offsetTop0Number by which to offset element's top CSS property.
    - **/ - function clonePosition(element, source, options) { - options = Object.extend({ - setLeft: true, - setTop: true, - setWidth: true, - setHeight: true, - offsetTop: 0, - offsetLeft: 0 - }, options || {}); - - // Find page position of source. - source = $(source); - element = $(element); - var p, delta, layout, styles = {}; - - var isAbsolute = Element.getStyle(element, 'position') === 'absolute'; - var parent = Element.getOffsetParent(element); - - if (options.setLeft || options.setTop) { - // We start by measuring the source's viewport offset. - p = Element.viewportOffset(source); - - // If the element we're altering is `position: fixed`, that's all the - // information we need: later we'll apply that offset to the `top` and - // `left` properties directly. - delta = [0, 0]; - - // But if it's `position: absolute`, we have to know where its offset - // parent is positioned and take those measurements into account as - // well. - if (isAbsolute && parent !== document.body) { - delta = Element.viewportOffset(parent); - } - } - - function pageScrollXY() { - var x = 0, y = 0; - if (Object.isNumber(window.pageXOffset)) { - // Modern browsers. - x = window.pageXOffset; - y = window.pageYOffset; - } else if (document.body && (document.body.scrollLeft || document.body.scrollTop)) { - x = document.body.scrollLeft; - y = document.body.scrollTop; - } - return { x: x, y: y }; - } - - // When the offset parent is the document body, we need to account for - // scroll offsets when we set `top` and `left`. (Unless the element is - // `position: fixed`; in that case we should always ignore scroll - // position.) - var pageXY = (isAbsolute && parent === document.body) ? pageScrollXY() : { x: 0, y: 0 }; - - // Set position. - if (options.setLeft) - styles.left = (p[0] + pageXY.x - delta[0] + options.offsetLeft) + 'px'; - if (options.setTop) - styles.top = (p[1] + pageXY.y - delta[1] + options.offsetTop) + 'px'; - - if (options.setWidth || options.setHeight) { - layout = Element.getLayout(source); - - // Use content box when setting width/height. If padding/border are - // different between source and target, that's for the user to fix; - // there's no good option for us. - if (options.setWidth) { - styles.width = layout.get('width') + 'px'; - } - if (options.setHeight) { - styles.height = layout.get('height') + 'px'; - } - } - - return Element.setStyle(element, styles); - } - - - Element.addMethods({ - getLayout: getLayout, - measure: measure, - getWidth: getWidth, - getHeight: getHeight, - getDimensions: getDimensions, - getOffsetParent: getOffsetParent, - cumulativeOffset: cumulativeOffset, - positionedOffset: positionedOffset, - cumulativeScrollOffset: cumulativeScrollOffset, - viewportOffset: viewportOffset, - absolutize: absolutize, - relativize: relativize, - scrollTo: scrollTo, - makePositioned: makePositioned, - undoPositioned: undoPositioned, - makeClipping: makeClipping, - undoClipping: undoClipping, - clonePosition: clonePosition - }); - - function isBody(element) { - return element.nodeName.toUpperCase() === 'BODY'; - } - - function isHtml(element) { - return element.nodeName.toUpperCase() === 'HTML'; - } - - function isDocument(element) { - return element.nodeType === Node.DOCUMENT_NODE; - } - - function isDetached(element) { - return element !== document.body && - !Element.descendantOf(element, document.body); - } - -})(); - -(function() { - /** - * document.viewport - * - * The `document.viewport` namespace contains methods that return information - * about the viewport — the rectangle that represents the portion of a web - * page within view. In other words, it's the browser window minus all chrome. - **/ - - var ROOT = null; - function getRootElement() { - if (ROOT) return ROOT; - ROOT = document.documentElement; - return ROOT; - } - - /** - * document.viewport.getDimensions() -> Object - * - * Returns an object containing viewport dimensions in the form - * `{ width: Number, height: Number }`. - * - * The _viewport_ is the subset of the browser window that a page occupies - * — the "usable" space in a browser window. - * - * ##### Example - * - * document.viewport.getDimensions(); - * //-> { width: 776, height: 580 } - **/ - function getDimensions() { - return { width: this.getWidth(), height: this.getHeight() }; - } - - /** - * document.viewport.getWidth() -> Number - * - * Returns the width of the viewport. - * - * Equivalent to calling `document.viewport.getDimensions().width`. - **/ - function getWidth() { - return getRootElement().clientWidth; - } - - /** - * document.viewport.getHeight() -> Number - * - * Returns the height of the viewport. - * - * Equivalent to `document.viewport.getDimensions().height`. - **/ - function getHeight() { - return getRootElement().clientHeight; - } - - /** - * document.viewport.getScrollOffsets() -> Array - * - * Returns the viewport's horizontal and vertical scroll offsets. - * - * Returns an array in the form of `[leftValue, topValue]`. Also accessible - * as properties: `{ left: leftValue, top: topValue }`. - * - * ##### Examples - * - * document.viewport.getScrollOffsets(); - * //-> { left: 0, top: 0 } - * - * window.scrollTo(0, 120); - * document.viewport.getScrollOffsets(); - * //-> { left: 0, top: 120 } - **/ - function getScrollOffsets() { - var x = window.pageXOffset || document.documentElement.scrollLeft || - document.body.scrollLeft; - var y = window.pageYOffset || document.documentElement.scrollTop || - document.body.scrollTop; - - return new Element.Offset(x, y); - } - - document.viewport = { - getDimensions: getDimensions, - getWidth: getWidth, - getHeight: getHeight, - getScrollOffsets: getScrollOffsets - }; - -})(); diff --git a/src/prototype/dom/selector.js b/src/prototype/dom/selector.js deleted file mode 100644 index 356e4ef01..000000000 --- a/src/prototype/dom/selector.js +++ /dev/null @@ -1,169 +0,0 @@ -/** section: DOM, related to: Prototype.Selector - * $$(cssRule...) -> [Element...] - * - * Takes an arbitrary number of CSS selectors (strings) and returns a document-order - * array of extended DOM elements that match any of them. - * - * Sometimes the usual tools from your DOM arsenal -- `document.getElementById` encapsulated - * by [[$]], `getElementsByTagName` and even Prototype's very own `getElementsByClassName` - * extensions -- just aren't enough to quickly find elements or collections of elements. - * If you know the DOM tree structure, you can simply resort to CSS selectors to get - * the job done. - * - * ##### Quick examples - * - * $$('div'); - * // -> all DIVs in the document. Same as document.getElementsByTagName('div'). - * // Nice addition, the elements you're getting back are already extended! - * - * $$('#contents'); - * // -> same as $('contents'), only it returns an array anyway (even though IDs must - * // be unique within a document). - * - * $$('li.faux'); - * // -> all LI elements with class 'faux' - * - * The [[$$]] function searches the entire document. For selector queries on more specific - * sections of a document, use [[Element.select]]. - * - * ##### Supported CSS syntax - * - * The [[$$]] function does not rely on the browser's internal CSS parsing capabilities - * (otherwise, we'd be in cross-browser trouble...), and therefore offers a consistent - * set of selectors across all supported browsers. - * - * ###### Supported in v1.5.0 - * - * * Type selector: tag names, as in `div`. - * * Descendant selector: the space(s) between other selectors, as in `#a li`. - * * Attribute selectors: the full CSS 2.1 set of `[attr]`, `[attr=value]`, `[attr~=value]` - * and `[attr|=value]`. It also supports `[attr!=value]`. If the value you're matching - * against includes a space, be sure to enclose the value in quotation marks (`[title="Hello World!"]`). - * * Class selector: CSS class names, as in `.highlighted` or `.example.wrong`. - * * ID selector: as in `#item1`. - * - * ###### Supported from v1.5.1 - * - * Virtually all of [CSS3](http://www.w3.org/TR/2001/CR-css3-selectors-20011113/#selectors) - * is supported, with the exception of pseudo-elements (like `::first-letter`) and some - * pseudo-classes (like `:hover`). Some examples of new selectors that can be used in 1.5.1: - * - * * Child selector: selects immediate descendants, as in `#a > li`. - * * Attribute selectors: all attribute operators are supported, including `~=` (matches - * part of a space-delimited attribute value, like `rel` or `class`); `^=` (matches the - * beginning of a value); `$=` (matches the end of a value); and `*=` (matches any part - * of the value). - * * The `:not` pseudo-class, as in `#a *:not(li)` (matches all descendants of `#a` that - * aren't LIs). - * * All the `:nth`, `:first`, and `:last` pseudo-classes. Examples include `tr:nth-child(even)` - * (all even table rows), `li:first-child` (the first item in any list), or `p:nth-last-of-type(3)` - * (the third-to-last paragraph on the page). - * * The `:empty` pseudo-class (for selecting elements without children or text content). - * * The `:enabled`, `:disabled`, and `:checked` pseudo-classes (for use with form controls). - * - * ##### Examples - * - * $$('#contents a[rel]'); - * // -> all links inside the element of ID "contents" with a rel attribute - * - * $$('a[href="#"]'); - * // -> all links with a href attribute of value "#" (eyeew!) - * - * $$('#navbar a', '#sidebar a'); - * // -> all links within the elements of ID "navbar" or "sidebar" - * - * **With version 1.5.1 and above** you can do various types of advanced selectors: - * - * $$('a:not([rel~=nofollow])'); - * // -> all links, excluding those whose rel attribute contains the word "nofollow" - * - * $$('table tbody > tr:nth-child(even)'); - * // -> all even rows within all table bodies - * - * $$('div:empty'); - * // -> all DIVs without content (i.e., whitespace-only) -**/ -var $$ = function() { - var expression = $A(arguments).join(', '); - return Prototype.Selector.select(expression, document); -}; - -/** - * Prototype.Selector - * - * A namespace that acts as a wrapper around - * the choosen selector engine (Sizzle by default). - * -**/ -Prototype.Selector = (function() { - - var K = Prototype.K; - - /** - * Prototype.Selector.select(expression[, root = document]) -> [Element...] - * - expression (String): A CSS selector. - * - root (Element | document): A "scope" to search within. All results will - * be descendants of this node. - * - * Searches `root` for elements that match the provided CSS selector and returns an - * array of extended [[Element]] objects. - **/ - function select() { - throw new Error('Method "Prototype.Selector.select" must be defined.'); - } - - /** - * Prototype.Selector.match(element, expression) -> Boolean - * - element (Element): a DOM element. - * - expression (String): A CSS selector. - * - * Tests whether `element` matches the CSS selector. - **/ - function match() { - throw new Error('Method "Prototype.Selector.match" must be defined.'); - } - - /** - * Prototype.Selector.find(elements, expression[, index = 0]) -> Element - * - elements (Enumerable): a collection of DOM elements. - * - expression (String): A CSS selector. - * - index (Number): Numeric index of the match to return, defaults to 0. - * - * Filters the given collection of elements with `expression` and returns the - * first matching element (or the `index`th matching element if `index` is - * specified). - **/ - function find(elements, expression, index) { - index = index || 0; - var match = Prototype.Selector.match, length = elements.length, matchIndex = 0, i; - - for (i = 0; i < length; i++) { - if (match(elements[i], expression) && index == matchIndex++) { - return elements[i]; - } - } - } - - /** alias of: Element.extend - * Prototype.Selector.extendElement(element) -> Element - **/ - var extendElement = K; - - /** - * Prototype.Selector.extendElements(elements) -> Enumerable - * - elements (Enumerable): a collection of DOM elements. - * - * If necessary, extends the elements contained in `elements` - * and returns `elements` untouched. This is provided as a - * convenience method for selector engine wrapper implementors. - **/ - var extendElements = K; - - return { - select: select, - match: match, - find: find, - extendElements: K, - extendElement: K - }; -})(); diff --git a/src/prototype/lang.js b/src/prototype/lang.js deleted file mode 100644 index b24801cee..000000000 --- a/src/prototype/lang.js +++ /dev/null @@ -1,81 +0,0 @@ -//= compat -//= require "lang/class" -//= require "lang/object" -//= require "lang/function" -//= require "lang/regexp" -//= require "lang/periodical_executer" -//= require "lang/string" -//= require "lang/template" -//= require "lang/enumerable" -//= require "lang/array" -//= require "lang/hash" -//= require "lang/number" -//= require "lang/range" - -/** - * == Language == - * - * Additions to JavaScript's "standard library" and extensions to - * built-in JavaScript objects. -**/ - -var Abstract = { }; - -/** section: Language - * Try -**/ - -/** deprecated - * Try.these(function...) -> ? - * - function (Function): A function that may throw an exception. - * - * Accepts an arbitrary number of functions and returns the result of the - * first one that doesn't throw an error. - * - * **This method is deprecated.** - * - *
    More information
    - * - * [[Try.these]] provides a simple idiom for trying out blocks of code in - * sequence. Such a sequence of attempts usually represents a downgrading - * approach to obtaining a given feature. - * - * In this example from Prototype's [[Ajax section]] internals, we want to get an - * `XMLHttpRequest` object. Internet Explorer 8 and earlier, however, does not - * provide it as a vanilla JavaScript object, and will throw an error if we - * attempt a simple instantiation. Also, over time, its proprietary way - * evolved, changing COM interface names. - * - * [[Try.these]] will try several ways in sequence, from the best (and, - * theoretically, most widespread) one to the oldest and rarest way, returning - * the result of the first successful function. - * - * If none of the blocks succeeded, [[Try.these]] will return `undefined`, which - * will cause the `Ajax.getTransport` method in the example below to return - * `false`, provided as a fallback result value. - * - * var Ajax = { - * getTransport: function() { - * return Try.these( - * function() { return new XMLHttpRequest() }, - * function() { return new ActiveXObject('Msxml2.XMLHTTP') }, - * function() { return new ActiveXObject('Microsoft.XMLHTTP') } - * ) || false; - * } - * }; - **/ -var Try = { - these: function() { - var returnValue; - - for (var i = 0, length = arguments.length; i < length; i++) { - var lambda = arguments[i]; - try { - returnValue = lambda(); - break; - } catch (e) { } - } - - return returnValue; - } -}; diff --git a/src/prototype/lang/array.js b/src/prototype/lang/array.js deleted file mode 100644 index f8d727d1b..000000000 --- a/src/prototype/lang/array.js +++ /dev/null @@ -1,483 +0,0 @@ -/** section: Language, related to: Array - * $A(iterable) -> Array - * - * Accepts an array-like collection (anything with numeric indices) and returns - * its equivalent as an actual [[Array]] object. This method is a convenience - * alias of [[Array.from]], but is the preferred way of casting to an [[Array]]. - * - * The primary use of [[$A]] is to obtain an actual [[Array]] object based on - * anything that could pass as an array (e.g. the `NodeList` or - * `HTMLCollection` objects returned by numerous DOM methods, or the predefined - * `arguments` reference within your functions). - * - * The reason you would want an actual [[Array]] is simple: - * [[Array Prototype extends Array]] to equip it with numerous extra methods, - * and also mixes in the [[Enumerable]] module, which brings in another - * boatload of nifty methods. Therefore, in Prototype, actual [[Array]]s trump - * any other collection type you might otherwise get. - * - * The conversion performed is rather simple: `null`, `undefined` and `false` become - * an empty array; any object featuring an explicit `toArray` method (as many Prototype - * objects do) has it invoked; otherwise, we assume the argument "looks like an array" - * (e.g. features a `length` property and the `[]` operator), and iterate over its components - * in the usual way. - * - * When passed an array, [[$A]] _makes a copy_ of that array and returns it. - * - * ##### Examples - * - * The well-known DOM method [`document.getElementsByTagName()`](http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-A6C9094) - * doesn't return an [[Array]], but a `NodeList` object that implements the basic array - * "interface.": - * - * var paras = $A(document.getElementsByTagName('p')); - * paras.each(Element.hide); - * $(paras.last()).show(); - * - * Notice we had to use [[Enumerable#each each]] and [[Element.hide]] because - * [[$A]] doesn't perform DOM extensions, since the array could contain - * anything (not just DOM elements). To use the [[Element#hide]] instance - * method we first must make sure all the target elements are extended: - * - * $A(document.getElementsByTagName('p')).map(Element.extend).invoke('hide'); - * - * Want to display your arguments easily? [[Array]] features a `join` method, but the `arguments` - * value that exists in all functions *does not* inherit from [[Array]]. So, the tough - * way, or the easy way? - * - * // The hard way... - * function showArgs() { - * alert(Array.prototype.join.call(arguments, ', ')); - * } - * - * // The easy way... - * function showArgs() { - * alert($A(arguments).join(', ')); - * } -**/ - -function $A(iterable) { - if (!iterable) return []; - if (iterable.toArray) return iterable.toArray(); - var length = iterable.length || 0, results = new Array(length); - while (length--) results[length] = iterable[length]; - return results; -} - -/** section: Language, related to: Array - * $w(String) -> Array - * - * Splits a string into an [[Array]], treating all whitespace as delimiters. Equivalent - * to Ruby's `%w{foo bar}` or Perl's `qw(foo bar)`. - * - * This is one of those life-savers for people who just hate commas in literal arrays :-) - * - * ### Examples - * - * $w('apples bananas kiwis') - * // -> ['apples', 'bananas', 'kiwis'] - * - * This can slightly shorten code when writing simple iterations: - * - * $w('apples bananas kiwis').each(function(fruit){ - * var message = 'I like ' + fruit - * // do something with the message - * }) - * - * This also becomes sweet when combined with [[Element]] functions: - * - * $w('ads navbar funkyLinks').each(Element.hide); -**/ - -function $w(string) { - if (!Object.isString(string)) return []; - string = string.strip(); - return string ? string.split(/\s+/) : []; -} - -/** alias of: $A - * Array.from(iterable) -> Array -**/ -Array.from = $A; - -/** section: Language - * class Array - * includes Enumerable - * - * Prototype extends all native JavaScript arrays with quite a few powerful - * methods. - * - * This is done in two ways: - * - * * It mixes in the [[Enumerable]] module, which brings in a ton of methods. - * * It adds quite a few extra methods, which are documented in this section. - * - * With Prototype, arrays become much, much more than the trivial objects we - * used to manipulate, limiting ourselves to using their `length` property and - * their `[]` indexing operator. They become very powerful objects that - * greatly simplify the code for 99% of the common use cases involving them. - * - * ##### Why you should stop using for...in to iterate - * - * Many JavaScript authors have been misled into using the `for...in` JavaScript - * construct to loop over array elements. This kind of code just won't work - * with Prototype. - * - * The ECMA 262 standard, which defines ECMAScript 3rd edition, supposedly - * implemented by all major browsers including MSIE, defines ten methods - * on [[Array]] (§15.4.4), including nice methods like `concat`, `join`, - * `pop`, and `push`. - * - * This same standard explicitly defines that the `for...in` construct (§12.6.4) - * exists to enumerate the properties of the object appearing on the right side - * of the `in` keyword. Only properties specifically marked as _non-enumerable_ - * are ignored by such a loop. By default, the `prototype` and `length` - * properties are so marked, which prevents you from enumerating over array - * methods when using for...in. This comfort led developers to use `for...in` as a - * shortcut for indexing loops, when it is not its actual purpose. - * - * However, Prototype has no way to mark the methods it adds to - * `Array.prototype` as non-enumerable. Therefore, using `for...in` on arrays - * when using Prototype will enumerate all extended methods as well, such as - * those coming from the [[Enumerable]] module, and those Prototype puts in the - * [[Array]] namespace (listed further below). - * - * ##### What you should use instead - * - * You can revert to vanilla loops: - * - * for (var index = 0; index < myArray.length; ++index) { - * var item = myArray[index]; - * // Your code working on item here... - * } - * - * Or you can use iterators, such as [[Array#each]]: - * - * myArray.each(function(item) { - * // Your code working on item here... - * }); - * - * The inability to use `for...in` on arrays is not much of a burden: as you'll - * see, most of what you used to loop over arrays for can be concisely done - * using the new methods provided by Array or the mixed-in [[Enumerable]] - * module. So manual loops should be fairly rare. - * - * ##### A note on performance - * - * Should you have a very large array, using iterators with lexical closures - * (anonymous functions that you pass to the iterators and that get invoked at - * every loop iteration) in methods like [[Array#each]] — _or_ relying on - * repetitive array construction (such as uniq), may yield unsatisfactory - * performance. In such cases, you're better off writing manual indexing loops, - * but take care then to cache the length property and use the prefix `++` - * operator: - * - * // Custom loop with cached length property: maximum full-loop - * // performance on very large arrays! - * for (var index = 0, len = myArray.length; index < len; ++index) { - * var item = myArray[index]; - * // Your code working on item here... - * } - * -**/ - -(function() { - var arrayProto = Array.prototype, - slice = arrayProto.slice, - _each = arrayProto.forEach; // use native browser JS 1.6 implementation if available - - // Note that #map, #filter, #some, and #every take some extra steps for - // ES5 compliance: the context in which they're called is coerced to an - // object, and that object's `length` property is coerced to a finite - // integer. This makes it easier to use the methods as generics. - // - // This means that they behave a little differently from other methods in - // `Enumerable`/`Array` that don't collide with ES5, but that's OK. - - var filter = arrayProto.filter, - map = wrapNative(arrayProto.map), - some = wrapNative(arrayProto.some), - every = wrapNative(arrayProto.every); - - /** - * Array#clear() -> Array - * - * Clears the array (makes it empty) and returns the array reference. - * - * ##### Example - * - * var guys = ['Sam', 'Justin', 'Andrew', 'Dan']; - * guys.clear(); - * // -> [] - * guys - * // -> [] - **/ - function clear() { - this.length = 0; - return this; - } - - /** - * Array#first() -> ? - * - * Returns the array's first item (e.g., `array[0]`). - **/ - function first() { - return this[0]; - } - - /** - * Array#last() -> ? - * - * Returns the array's last item (e.g., `array[array.length - 1]`). - **/ - function last() { - return this[this.length - 1]; - } - - /** - * Array#compact() -> Array - * - * Returns a **copy** of the array without any `null` or `undefined` values. - * - * ##### Example - * - * var orig = [undefined, 'A', undefined, 'B', null, 'C']; - * var copy = orig.compact(); - * // orig -> [undefined, 'A', undefined, 'B', null, 'C']; - * // copy -> ['A', 'B', 'C']; - **/ - function compact() { - return this.select(function(value) { - return value != null; - }); - } - - /** - * Array#flatten() -> Array - * - * Returns a flattened (one-dimensional) copy of the array, leaving - * the original array unchanged. - * - * Nested arrays are recursively injected inline. This can prove very - * useful when handling the results of a recursive collection algorithm, - * for instance. - * - * ##### Example - * - * var a = ['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]]; - * var b = a.flatten(); - * // a -> ['frank', ['bob', 'lisa'], ['jill', ['tom', 'sally']]] - * // b -> ['frank', 'bob', 'lisa', 'jill', 'tom', 'sally'] - **/ - function flatten() { - return this.inject([], function(array, value) { - if (Object.isArray(value)) - return array.concat(value.flatten()); - array.push(value); - return array; - }); - } - - /** - * Array#without(value[, value...]) -> Array - * - value (?): A value to exclude. - * - * Produces a new version of the array that does not contain any of the - * specified values, leaving the original array unchanged. - * - * ##### Examples - * - * [3, 5, 6].without(3) - * // -> [5, 6] - * - * [3, 5, 6, 20].without(20, 6) - * // -> [3, 5] - **/ - function without() { - var values = slice.call(arguments, 0); - return this.select(function(value) { - return !values.include(value); - }); - } - - /** - * Array#reverse([inline = true]) -> Array - * - inline (Boolean): Whether to modify the array in place. Defaults to `true`. - * Clones the original array when `false`. - * - * Reverses the array's contents, optionally cloning it first. - * - * ##### Examples - * - * // Making a copy - * var nums = [3, 5, 6, 1, 20]; - * var rev = nums.reverse(false); - * // nums -> [3, 5, 6, 1, 20] - * // rev -> [20, 1, 6, 5, 3] - * - * // Working inline - * var nums = [3, 5, 6, 1, 20]; - * nums.reverse(); - * // nums -> [20, 1, 6, 5, 3] - **/ - function reverse(inline) { - return (inline === false ? this.toArray() : this)._reverse(); - } - - /** - * Array#uniq([sorted = false]) -> Array - * - sorted (Boolean): Whether the array has already been sorted. If `true`, - * a less-costly algorithm will be used. - * - * Produces a duplicate-free version of an array. If no duplicates are - * found, the original array is returned. - * - * On large arrays when `sorted` is `false`, this method has a potentially - * large performance cost. - * - * ##### Examples - * - * [1, 3, 2, 1].uniq(); - * // -> [1, 2, 3] - * - * ['A', 'a'].uniq(); - * // -> ['A', 'a'] (because String comparison is case-sensitive) - **/ - function uniq(sorted) { - return this.inject([], function(array, value, index) { - if (0 == index || (sorted ? array.last() != value : !array.include(value))) - array.push(value); - return array; - }); - } - - /** - * Array#intersect(array) -> Array - * - array (Array): A collection of values. - * - * Returns an array containing every item that is shared between the two - * given arrays. - **/ - function intersect(array) { - return this.uniq().findAll(function(item) { - return array.indexOf(item) !== -1; - }); - } - - /** alias of: Array#clone - * Array#toArray() -> Array - **/ - - /** - * Array#clone() -> Array - * - * Returns a duplicate of the array, leaving the original array intact. - **/ - function clone() { - return slice.call(this, 0); - } - - /** related to: Enumerable#size - * Array#size() -> Number - * - * Returns the size of the array (e.g., `array.length`). - * - * This is just a local optimization of the mixed-in [[Enumerable#size]] - * which avoids array cloning and uses the array's native length property. - **/ - function size() { - return this.length; - } - - /** related to: Object.inspect - * Array#inspect() -> String - * - * Returns the debug-oriented string representation of an array. - * - * ##### Example - * - * ['Apples', {good: 'yes', bad: 'no'}, 3, 34].inspect() - * // -> "['Apples', [object Object], 3, 34]" - **/ - function inspect() { - return '[' + this.map(Object.inspect).join(', ') + ']'; - } - - // Certain ES5 array methods have the same names as Prototype array methods - // and perform the same functions. - // - // Prototype's implementations of these methods differ from the ES5 spec in - // the way a missing iterator function is handled. Prototype uses - // `Prototype.K` as a default iterator, while ES5 specifies that a - // `TypeError` must be thrown. Implementing the ES5 spec completely would - // break backward compatibility and would force users to pass `Prototype.K` - // manually. - // - // Instead, if native versions of these methods exist, we wrap the existing - // methods with our own behavior. This has very little performance impact. - // It violates the spec by suppressing `TypeError`s for certain methods, - // but that's an acceptable trade-off. - - function wrapNative(method) { - return function() { - if (arguments.length === 0) { - // No iterator was given. Instead of throwing a `TypeError`, use - // `Prototype.K` as the default iterator. - return method.call(this, Prototype.K); - } else if (arguments[0] === undefined) { - // Same as above. - var args = slice.call(arguments, 1); - args.unshift(Prototype.K); - return method.apply(this, args); - } else { - // Pass straight through to the native method. - return method.apply(this, arguments); - } - }; - } - - // We used to define an `inject` method here that relied on ES5's - // `Array#reduce` (if present), but using `reduce` prevents us from - // catching a thrown `$break`. So arrays now use the standard - // `Enumerable.inject` like they did previously. - - Object.extend(arrayProto, Enumerable); - - // Enumerable's `entries` method is no longer safe to mixin to arrays, as - // it conflicts with an ES6 method. But it can still be mixed into other - // things. - if (arrayProto.entries === Enumerable.entries) { - delete arrayProto.entries; - } - - if (!arrayProto._reverse) - arrayProto._reverse = arrayProto.reverse; - - Object.extend(arrayProto, { - _each: _each, - - map: map, - collect: map, - select: filter, - findAll: filter, - some: some, - any: some, - every: every, - all: every, - - clear: clear, - first: first, - last: last, - compact: compact, - flatten: flatten, - without: without, - reverse: reverse, - uniq: uniq, - intersect: intersect, - clone: clone, - toArray: clone, - size: size, - inspect: inspect - }); -})(); diff --git a/src/prototype/lang/class.js b/src/prototype/lang/class.js deleted file mode 100644 index e0167f74f..000000000 --- a/src/prototype/lang/class.js +++ /dev/null @@ -1,179 +0,0 @@ -/* Based on Alex Arnell's inheritance implementation. */ - -/** section: Language - * class Class - * - * Manages Prototype's class-based OOP system. - * - * Refer to Prototype's web site for a [tutorial on classes and - * inheritance](http://prototypejs.org/learn/class-inheritance). -**/ -var Class = (function() { - - /** - * Class.create([superclass][, methods...]) -> Class - * - superclass (Class): The optional superclass to inherit methods from. - * - methods (Object): An object whose properties will be "mixed-in" to the - * new class. Any number of mixins can be added; later mixins take - * precedence. - * - * [[Class.create]] creates a class and returns a constructor function for - * instances of the class. Calling the constructor function (typically as - * part of a `new` statement) will invoke the class's `initialize` method. - * - * [[Class.create]] accepts two kinds of arguments. If the first argument is - * a [[Class]], it's used as the new class's superclass, and all its methods - * are inherited. Otherwise, any arguments passed are treated as objects, - * and their methods are copied over ("mixed in") as instance methods of the - * new class. In cases of method name overlap, later arguments take - * precedence over earlier arguments. - * - * If a subclass overrides an instance method declared in a superclass, the - * subclass's method can still access the original method. To do so, declare - * the subclass's method as normal, but insert `$super` as the first - * argument. This makes `$super` available as a method for use within the - * function. - * - * To extend a class after it has been defined, use [[Class#addMethods]]. - * - * For details, see the - * [inheritance tutorial](http://prototypejs.org/learn/class-inheritance) - * on the Prototype website. - **/ - function subclass() {}; - function create() { - var parent = null, properties = $A(arguments); - if (Object.isFunction(properties[0])) - parent = properties.shift(); - - function klass() { - this.initialize.apply(this, arguments); - } - - Object.extend(klass, Class.Methods); - klass.superclass = parent; - klass.subclasses = []; - - if (parent) { - subclass.prototype = parent.prototype; - klass.prototype = new subclass; - parent.subclasses.push(klass); - } - - for (var i = 0, length = properties.length; i < length; i++) - klass.addMethods(properties[i]); - - if (!klass.prototype.initialize) - klass.prototype.initialize = Prototype.emptyFunction; - - klass.prototype.constructor = klass; - return klass; - } - - /** - * Class#addMethods(methods) -> Class - * - methods (Object): The methods to add to the class. - * - * Adds methods to an existing class. - * - * [[Class#addMethods]] is a method available on classes that have been - * defined with [[Class.create]]. It can be used to add new instance methods - * to that class, or overwrite existing methods, after the class has been - * defined. - * - * New methods propagate down the inheritance chain. If the class has - * subclasses, those subclasses will receive the new methods — even in - * the context of `$super` calls. The new methods also propagate to instances - * of the class and of all its subclasses, even those that have already been - * instantiated. - * - * ##### Examples - * - * var Animal = Class.create({ - * initialize: function(name, sound) { - * this.name = name; - * this.sound = sound; - * }, - * - * speak: function() { - * alert(this.name + " says: " + this.sound + "!"); - * } - * }); - * - * // subclassing Animal - * var Snake = Class.create(Animal, { - * initialize: function($super, name) { - * $super(name, 'hissssssssss'); - * } - * }); - * - * var ringneck = new Snake("Ringneck"); - * ringneck.speak(); - * - * //-> alerts "Ringneck says: hissssssss!" - * - * // adding Snake#speak (with a supercall) - * Snake.addMethods({ - * speak: function($super) { - * $super(); - * alert("You should probably run. He looks really mad."); - * } - * }); - * - * ringneck.speak(); - * //-> alerts "Ringneck says: hissssssss!" - * //-> alerts "You should probably run. He looks really mad." - * - * // redefining Animal#speak - * Animal.addMethods({ - * speak: function() { - * alert(this.name + 'snarls: ' + this.sound + '!'); - * } - * }); - * - * ringneck.speak(); - * //-> alerts "Ringneck snarls: hissssssss!" - * //-> alerts "You should probably run. He looks really mad." - **/ - function addMethods(source) { - var ancestor = this.superclass && this.superclass.prototype, - properties = Object.keys(source); - - for (var i = 0, length = properties.length; i < length; i++) { - var property = properties[i], value = source[property]; - if (ancestor && Object.isFunction(value) && - value.argumentNames()[0] == "$super") { - var method = value; - value = (function(m) { - return function() { return ancestor[m].apply(this, arguments); }; - })(property).wrap(method); - - // We used to use `bind` to ensure that `toString` and `valueOf` - // methods were called in the proper context, but now that we're - // relying on native bind and/or an existing polyfill, we can't rely - // on the nuanced behavior of whatever `bind` implementation is on - // the page. - // - // MDC's polyfill, for instance, doesn't like binding functions that - // haven't got a `prototype` property defined. - value.valueOf = (function(method) { - return function() { return method.valueOf.call(method); }; - })(method); - - value.toString = (function(method) { - return function() { return method.toString.call(method); }; - })(method); - } - this.prototype[property] = value; - } - - return this; - } - - return { - create: create, - Methods: { - addMethods: addMethods - } - }; -})(); diff --git a/src/prototype/lang/enumerable.js b/src/prototype/lang/enumerable.js deleted file mode 100644 index f55eac347..000000000 --- a/src/prototype/lang/enumerable.js +++ /dev/null @@ -1,853 +0,0 @@ -/** section: Language - * mixin Enumerable - * - * [[Enumerable]] provides a large set of useful methods for enumerations — - * objects that act as collections of values. It is a cornerstone of - * Prototype. - * - * [[Enumerable]] is a _mixin_: a set of methods intended not for standalone - * use, but for incorporation into other objects. - * - * Prototype mixes [[Enumerable]] into several classes. The most visible cases - * are [[Array]] and [[Hash]], but you'll find it in less obvious spots as - * well, such as in [[ObjectRange]] and various DOM- or Ajax-related objects. - * - * ##### The `context` parameter - * - * Every method of [[Enumerable]] that takes an iterator also takes the "context - * object" as the next (optional) parameter. The context object is what the - * iterator will be _bound_ to — what the keyword `this` will refer to inside - * the iterator. - * - * var myObject = {}; - * - * ['foo', 'bar', 'baz'].each(function(name, index) { - * this[name] = index; - * }, myObject); // we have specified the context - * - * myObject; - * // -> { foo: 0, bar: 1, baz: 2} - * - * If there is no `context` argument, the iterator function will execute in - * the scope from which the [[Enumerable]] method itself was called. - * - * ##### Flow control - * - * You might find yourself missing the `break` and `continue` keywords that - * are available in ordinary `for` loops. If you need to break out of an - * enumeration before it's done, you can throw a special object named - * `$break`: - * - * var myObject = {}; - * - * ['foo', 'bar', 'baz', 'thud'].each( function(name, index) { - * if (name === 'baz') throw $break; - * myObject[name] = index; - * }); - * - * myObject; - * // -> { foo: 0, bar: 1 } - * - * Though we're technically throwing an exception, the `each` method knows - * to catch a thrown `$break` object and treat it as a command to stop - * iterating. (_Any_ exception thrown within an iterator will stop - * iteration, but only `$break` will be caught and suppressed.) - * - * If you need `continue`-like behavior, you can simply return early from - * your iterator: - * - * var myObject = {}; - * - * ['foo', 'bar', 'baz', 'thud'].each( function(name, index) { - * if (name === 'baz') return; - * myObject[name] = index; - * }); - * - * myObject; - * // -> { foo: 0, bar: 1, thud: 3 } - * - * ##### Mixing [[Enumerable]] into your own objects - * - * So, let's say you've created your very own collection-like object (say, - * some sort of Set, or perhaps something that dynamically fetches data - * ranges from the server side, lazy-loading style). You want to be able to - * mix [[Enumerable]] in (and we commend you for it). How do you go about this? - * - * The Enumerable module basically makes only one requirement on your object: - * it must provide a method named `_each` (note the leading underscore) that - * will accept a function as its unique argument, and will contain the actual - * "raw iteration" algorithm, invoking its argument with each element in turn. - * - * As detailed in the documentation for [[Enumerable#each]], [[Enumerable]] - * provides all the extra layers (handling iteration short-circuits, passing - * numeric indices, etc.). You just need to implement the actual iteration, - * as fits your internal structure. - * - * If you're still confused, just have a look at the Prototype source code for - * [[Array]], [[Hash]], or [[ObjectRange]]. They all begin with their own - * `_each` method, which should help you grasp the idea. - * - * Once you're done with this, you just need to mix [[Enumerable]] in, which - * you'll usually do before defining your methods, so as to make sure whatever - * overrides you provide for [[Enumerable]] methods will indeed prevail. In - * short, your code will probably end up looking like this: - * - * - * var YourObject = Class.create(Enumerable, { - * initialize: function() { // with whatever constructor arguments you need - * // Your construction code - * }, - * - * _each: function(iterator) { - * // Your iteration code, invoking iterator at every turn - * }, - * - * // Your other methods here, including Enumerable overrides - * }); - * - * Then, obviously, your object can be used like this: - * - * var obj = new YourObject(); - * // Populate the collection somehow - * obj.pluck('somePropName'); - * obj.invoke('someMethodName'); - * obj.size(); - * // etc. - * -**/ - -var $break = { }; - -var Enumerable = (function() { - /** - * Enumerable#each(iterator[, context]) -> Enumerable - * - iterator (Function): A `Function` that expects an item in the - * collection as the first argument and a numerical index as the second. - * - context (Object): The scope in which to call `iterator`. Affects what - * the keyword `this` means inside `iterator`. - * - * Calls `iterator` for each item in the collection. - * - * ##### Examples - * - * ['one', 'two', 'three'].each(alert); - * // Alerts "one", then alerts "two", then alerts "three" - * - * ##### Built-In Variants - * - * Most of the common use cases for `each` are already available pre-coded - * as other methods on [[Enumerable]]. Whether you want to find the first - * matching item in an enumeration, or transform it, or determine whether it - * has any (or all) values matching a particular condition, [[Enumerable]] - * has a method to do that for you. - **/ - function each(iterator, context) { - try { - this._each(iterator, context); - } catch (e) { - if (e != $break) throw e; - } - return this; - } - - /** - * Enumerable#eachSlice(number[, iterator = Prototype.K[, context]]) -> Enumerable - * - number (Number): The number of items to include in each slice. - * - iterator (Function): An optional function to use to transform each - * element before it's included in the slice; if this is not provided, - * the element itself is included. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Groups items into chunks of the given size. The final "slice" may have - * fewer than `number` items; it won't "pad" the last group with empty - * values. For that behavior, use [[Enumerable#inGroupsOf]]. - * - * ##### Example - * - * var students = [ - * { name: 'Sunny', age: 20 }, - * { name: 'Audrey', age: 21 }, - * { name: 'Matt', age: 20 }, - * { name: 'Amelie', age: 26 }, - * { name: 'Will', age: 21 } - * ]; - * - * students.eachSlice(3, function(student) { - * return student.name; - * }); - * // -> [['Sunny', 'Audrey', 'Matt'], ['Amelie', 'Will']] - **/ - function eachSlice(number, iterator, context) { - var index = -number, slices = [], array = this.toArray(); - if (number < 1) return array; - while ((index += number) < array.length) - slices.push(array.slice(index, index+number)); - return slices.collect(iterator, context); - } - - /** - * Enumerable#all([iterator = Prototype.K[, context]]) -> Boolean - * - iterator (Function): An optional function to use to evaluate - * each element in the enumeration; the function should return the value to - * test. If this is not provided, the element itself is tested. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Determines whether all the elements are "truthy" (boolean-equivalent to - * `true`), either directly or through computation by the provided iterator. - * Stops on the first falsy element found (e.g., the first element that - * is boolean-equivalent to `false`, such as `undefined`, `0`, or indeed - * `false`); - * - * ##### Examples - * - * [].all(); - * // -> true (empty arrays have no elements that could be falsy) - * - * $R(1, 5).all(); - * // -> true (all values in [1..5] are truthy) - * - * [0, 1, 2].all(); - * // -> false (with only one loop cycle: 0 is falsy) - * - * [9, 10, 15].all(function(n) { return n >= 10; }); - * // -> false (the iterator returns false on 9) - **/ - function all(iterator, context) { - iterator = iterator || Prototype.K; - var result = true; - this.each(function(value, index) { - result = result && !!iterator.call(context, value, index, this); - if (!result) throw $break; - }, this); - return result; - } - - /** - * Enumerable#any([iterator = Prototype.K[, context]]) -> Boolean - * - iterator (Function): An optional function to use to evaluate each - * element in the enumeration; the function should return the value to - * test. If this is not provided, the element itself is tested. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Determines whether at least one element is truthy (boolean-equivalent to - * `true`), either directly or through computation by the provided iterator. - * - * ##### Examples - * - * [].any(); - * // -> false (empty arrays have no elements that could be truthy) - * - * $R(0, 2).any(); - * // -> true (on the second loop, 1 is truthy) - * - * [2, 4, 6, 8, 10].any(function(n) { return n > 5; }); - * // -> true (the iterator will return true on 6) - **/ - function any(iterator, context) { - iterator = iterator || Prototype.K; - var result = false; - this.each(function(value, index) { - if (result = !!iterator.call(context, value, index, this)) - throw $break; - }, this); - return result; - } - - /** - * Enumerable#collect([iterator = Prototype.K[, context]]) -> Array - * - iterator (Function): The iterator function to apply to each element - * in the enumeration. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Returns the result of applying `iterator` to each element. If no - * `iterator` is provided, the elements are simply copied to the - * returned array. - * - * ##### Examples - * - * ['Hitch', "Hiker's", 'Guide', 'to', 'the', 'Galaxy'].collect(function(s) { - * return s.charAt(0).toUpperCase(); - * }); - * // -> ['H', 'H', 'G', 'T', 'T', 'G'] - * - * $R(1,5).collect(function(n) { - * return n * n; - * }); - * // -> [1, 4, 9, 16, 25] - **/ - function collect(iterator, context) { - iterator = iterator || Prototype.K; - var results = []; - this.each(function(value, index) { - results.push(iterator.call(context, value, index, this)); - }, this); - return results; - } - - /** - * Enumerable#detect(iterator[, context]) -> firstElement | undefined - * - iterator (Function): The iterator function to apply to each element - * in the enumeration. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Returns the first element for which the iterator returns a truthy value. - * Aliased by the [[Enumerable#find]] method. - * - * ##### Example - * - * [1, 7, -2, -4, 5].detect(function(n) { return n < 0; }); - * // -> -2 - **/ - function detect(iterator, context) { - var result; - this.each(function(value, index) { - if (iterator.call(context, value, index, this)) { - result = value; - throw $break; - } - }, this); - return result; - } - - /** - * Enumerable#findAll(iterator[, context]) -> Array - * - iterator (Function): An iterator function to use to test the elements. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Returns all the elements for which the iterator returned a truthy value. - * For the opposite operation, see [[Enumerable#reject]]. - * - * ##### Example - * - * [1, 'two', 3, 'four', 5].findAll(Object.isString); - * // -> ['two', 'four'] - **/ - function findAll(iterator, context) { - var results = []; - this.each(function(value, index) { - if (iterator.call(context, value, index, this)) - results.push(value); - }, this); - return results; - } - - /** - * Enumerable#grep(filter[, iterator = Prototype.K[, context]]) -> Array - * - filter (RegExp | String | Object): The filter to apply to elements. This - * can be a `RegExp` instance, a regular expression [[String]], or any - * object with a `match` function. - * - iterator (Function): An optional function to apply to selected elements - * before including them in the result. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Returns an array containing all of the elements for which the given - * filter returns `true` (or a truthy value). If an iterator is provided, - * it is used to produce the returned value for each selected element; this - * is done *after* the element has been selected by the filter. - * - * If the given filter is a [[String]], it is converted into a `RegExp` - * object. To select elements, each element is passed into the filter's - * `match` function, which should return a truthy value to select the element - * or a falsy value not to. Note that the `RegExp` `match` function will - * convert elements to Strings to perform matching. - * - * ##### Examples - * - * // Get all strings containing a repeated letter - * ['hello', 'world', 'this', 'is', 'cool'].grep(/(.)\1/); - * // -> ['hello', 'cool'] - * - * // Get all numbers ending with 0 or 5 and subtract 1 from them - * $R(1, 30).grep(/[05]$/, function(n) { return n - 1; }); - * // -> [4, 9, 14, 19, 24, 29] - **/ - function grep(filter, iterator, context) { - iterator = iterator || Prototype.K; - var results = []; - - if (Object.isString(filter)) - filter = new RegExp(RegExp.escape(filter)); - - this.each(function(value, index) { - if (filter.match(value)) - results.push(iterator.call(context, value, index, this)); - }, this); - return results; - } - - /** - * Enumerable#include(object) -> Boolean - * - object (?): The object to look for. - * - * Determines whether a given object is in the enumerable or not, - * based on the `==` comparison operator (equality with implicit type - * conversion). - * - * ##### Examples - * - * $R(1, 15).include(10); - * // -> true - * - * ['hello', 'world'].include('HELLO'); - * // -> false ('hello' != 'HELLO') - * - * [1, 2, '3', '4', '5'].include(3); - * // -> true ('3' == 3) - **/ - function include(object) { - if (Object.isFunction(this.indexOf) && this.indexOf(object) != -1) - return true; - - var found = false; - this.each(function(value) { - if (value == object) { - found = true; - throw $break; - } - }); - return found; - } - - /** - * Enumerable#inGroupsOf(number[, fillWith = null]) -> [group...] - * - number (Number): The number of items to include in each group. - * - fillWith (Object): An optional filler to use if the last group needs - * any; defaults to `null`. - * - * Like [[Enumerable#eachSlice]], but pads out the last chunk with the - * specified value if necessary and doesn't support the `iterator` function. - * - * ##### Examples - * - * var students = [ - * { name: 'Sunny', age: 20 }, - * { name: 'Audrey', age: 21 }, - * { name: 'Matt', age: 20 }, - * { name: 'Amelie', age: 26 }, - * { name: 'Will', age: 21 } - * ]; - * - * students.inGroupsOf(2, { name: '', age: 0 }); - * // -> [ - * // [{ name: 'Sunny', age: 20 }, { name: 'Audrey', age: 21 }], - * // [{ name: 'Matt', age: 20 }, { name: 'Amelie', age: 26 }], - * // [{ name: 'Will', age: 21 }, { name: '', age: 0 }] - * // ] - **/ - function inGroupsOf(number, fillWith) { - fillWith = Object.isUndefined(fillWith) ? null : fillWith; - return this.eachSlice(number, function(slice) { - while(slice.length < number) slice.push(fillWith); - return slice; - }); - } - - /** - * Enumerable#inject(accumulator, iterator[, context]) -> accumulatedValue - * - accumulator (?): The initial value to which the `iterator` adds. - * - iterator (Function): An iterator function used to build the accumulated - * result. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Incrementally builds a result value based on the successive results - * of the iterator. This can be used for array construction, numerical - * sums/averages, etc. - * - * The `iterator` function is called once for each element in the - * enumeration, receiving the current value of the accumulator as its first - * argument, the element as its second argument, and the element's index as - * its third. It returns the new value for the accumulator. - * - * ##### Examples - * - * $R(1,10).inject(0, function(acc, n) { return acc + n; }); - * // -> 55 (sum of 1 to 10) - * - * ['a', 'b', 'c', 'd', 'e'].inject([], function(string, value, index) { - * if (index % 2 === 0) { // even numbers - * string += value; - * } - * return string; - * }); - * // -> 'ace' - **/ - function inject(memo, iterator, context) { - this.each(function(value, index) { - memo = iterator.call(context, memo, value, index, this); - }, this); - return memo; - } - - /** - * Enumerable#invoke(methodName[, arg...]) -> Array - * - methodName (String): The name of the method to invoke. - * - args (?): Optional arguments to pass to the method. - * - * Invokes the same method, with the same arguments, for all items in a - * collection. Returns an array of the results of the method calls. - * - * ##### Examples - * - * ['hello', 'world'].invoke('toUpperCase'); - * // -> ['HELLO', 'WORLD'] - * - * ['hello', 'world'].invoke('substring', 0, 3); - * // -> ['hel', 'wor'] - * - * $$('input').invoke('stopObserving', 'change'); - * // -> Stops observing the 'change' event on all input elements, - * // returns an array of the element references. - **/ - function invoke(method) { - var args = $A(arguments).slice(1); - return this.map(function(value) { - return value[method].apply(value, args); - }); - } - - /** related to: Enumerable#min - * Enumerable#max([iterator = Prototype.K[, context]]) -> maxValue - * - iterator (Function): An optional function to use to evaluate each - * element in the enumeration; the function should return the value to - * test. If this is not provided, the element itself is tested. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Returns the maximum element (or element-based `iterator` result), or - * `undefined` if the enumeration is empty. Elements are either compared - * directly, or by first calling `iterator` and comparing returned values. - * If multiple "max" elements (or results) are equivalent, the one closest - * to the end of the enumeration is returned. - * - * If provided, `iterator` is called with two arguments: The element being - * evaluated, and its index in the enumeration; it should return the value - * `max` should consider (and potentially return). - * - * ##### Examples - * - * ['c', 'b', 'a'].max(); - * // -> 'c' - * - * [1, 3, '3', 2].max(); - * // -> '3' (because both 3 and '3' are "max", and '3' was later) - * - * ['zero', 'one', 'two'].max(function(item) { return item.length; }); - * // -> 4 - **/ - function max(iterator, context) { - iterator = iterator || Prototype.K; - var result; - this.each(function(value, index) { - value = iterator.call(context, value, index, this); - if (result == null || value >= result) - result = value; - }, this); - return result; - } - - /** related to: Enumerable#max - * Enumerable#min([iterator = Prototype.K[, context]]) -> minValue - * - iterator (Function): An optional function to use to evaluate each - * element in the enumeration; the function should return the value to - * test. If this is not provided, the element itself is tested. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Returns the minimum element (or element-based `iterator` result), or - * `undefined` if the enumeration is empty. Elements are either compared - * directly, or by first calling `iterator` and comparing returned values. - * If multiple "min" elements (or results) are equivalent, the one closest - * to the *beginning* of the enumeration is returned. - * - * If provided, `iterator` is called with two arguments: The element being - * evaluated, and its index in the enumeration; it should return the value - * `min` should consider (and potentially return). - * - * ##### Examples - * - * ['c', 'b', 'a'].min(); - * // -> 'a' - * - * [3, 1, '1', 2].min(); - * // -> 1 (because both 1 and '1' are "min", and 1 was earlier) - * - * ['un', 'deux', 'trois'].min(function(item) { return item.length; }); - * // -> 2 - **/ - function min(iterator, context) { - iterator = iterator || Prototype.K; - var result; - this.each(function(value, index) { - value = iterator.call(context, value, index, this); - if (result == null || value < result) - result = value; - }, this); - return result; - } - - /** - * Enumerable#partition([iterator = Prototype.K[, context]]) -> [TrueArray, FalseArray] - * - iterator (Function): An optional function to use to evaluate each - * element in the enumeration; the function should return the value to - * test. If this is not provided, the element itself is tested. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Partitions the elements in two groups: those regarded as true, and those - * considered false. By default, regular JavaScript boolean equivalence - * (e.g., truthiness vs. falsiness) is used, but an iterator can be provided - * that computes a boolean representation of the elements. - * - * Using `partition` is more efficient than using [[Enumerable#findAll]] and - * then using [[Enumerable#reject]] because the enumeration is only processed - * once. - * - * ##### Examples - * - * ['hello', null, 42, false, true, , 17].partition(); - * // -> [['hello', 42, true, 17], [null, false, undefined]] - * - * $R(1, 10).partition(function(n) { - * return 0 == n % 2; - * }); - * // -> [[2, 4, 6, 8, 10], [1, 3, 5, 7, 9]] - **/ - function partition(iterator, context) { - iterator = iterator || Prototype.K; - var trues = [], falses = []; - this.each(function(value, index) { - (iterator.call(context, value, index, this) ? - trues : falses).push(value); - }, this); - return [trues, falses]; - } - - /** - * Enumerable#pluck(property) -> Array - * - property (String): The name of the property to fetch. - * - * Pre-baked implementation for a common use-case of [[Enumerable#collect]] - * and [[Enumerable#each]]: fetching the same property for all of the - * elements. Returns an array of the property values. - * - * ##### Example - * - * ['hello', 'world', 'this', 'is', 'nice'].pluck('length'); - * // -> [5, 5, 4, 2, 4] - **/ - function pluck(property) { - var results = []; - this.each(function(value) { - results.push(value[property]); - }); - return results; - } - - /** - * Enumerable#reject(iterator[, context]) -> Array - * - iterator (Function): An iterator function to use to test the elements. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Returns all the elements for which the iterator returns a falsy value. - * For the opposite operation, see [[Enumerable#findAll]]. - * - * ##### Example - * - * [1, "two", 3, "four", 5].reject(Object.isString); - * // -> [1, 3, 5] - **/ - function reject(iterator, context) { - var results = []; - this.each(function(value, index) { - if (!iterator.call(context, value, index, this)) - results.push(value); - }, this); - return results; - } - - /** - * Enumerable#sortBy(iterator[, context]) -> Array - * - iterator (Function): The function to use to compute the criterion for - * each element in the enumeration. - * - context (Object): An optional object to use as `this` within - * calls to the iterator. - * - * Creates a custom-sorted array of the elements based on the criteria - * computed, for each element, by the iterator. Computed criteria must have - * well-defined ordering semantics (i.e. the `<` operator must exist between - * any two criteria). - * - * [[Enumerable#sortBy]] does not guarantee a *stable* sort; adjacent - * equivalent elements may be swapped. - * - * ##### Example - * - * ['hello', 'world', 'this', 'is', 'nice'].sortBy(function(s) { - * return s.length; - * }); - * // -> ['is', 'nice', 'this', 'world', 'hello'] - **/ - function sortBy(iterator, context) { - return this.map(function(value, index) { - return { - value: value, - criteria: iterator.call(context, value, index, this) - }; - }, this).sort(function(left, right) { - var a = left.criteria, b = right.criteria; - return a < b ? -1 : a > b ? 1 : 0; - }).pluck('value'); - } - - /** - * Enumerable#toArray() -> Array - * - * Returns an Array containing the elements of the enumeration. - * - * ##### Example - * - * $R(1, 5).toArray(); - * // -> [1, 2, 3, 4, 5] - * - * $H({ name: 'Sunny', age: 20 }).toArray(); - * // -> [['name', 'Sunny'], ['age', 20]] - **/ - function toArray() { - return this.map(); - } - - /** - * Enumerable#zip(sequence...[, iterator = Prototype.K]) -> Array - * - sequence (Object): A sequence to zip with this enumerable (there can - * be several of these if desired). - * - iterator (Function): Optional function to use to transform the tuples - * once generated; this is always the last argument provided. - * - * Zips together (think of the zipper on a pair of trousers) 2+ sequences, - * returning a new array of tuples. Each tuple is an array containing one - * value per original sequence. Tuples can be transformed to something else - * by applying the optional `iterator` on them. - * - * If supplied, `iterator` is called with each tuple as its only argument - * and should return the value to use in place of that tuple. - * - * ##### Examples - * - * var firstNames = ['Jane', 'Nitin', 'Guy']; - * var lastNames = ['Doe', 'Patel', 'Forcier']; - * var ages = [23, 41, 17]; - * - * firstNames.zip(lastNames); - * // -> [['Jane', 'Doe'], ['Nitin', 'Patel'], ['Guy', 'Forcier']] - * - * firstNames.zip(lastNames, ages); - * // -> [['Jane', 'Doe', 23], ['Nitin', 'Patel', 41], ['Guy', 'Forcier', 17]] - * - * firstNames.zip(lastNames, ages, function(tuple) { - * return tuple[0] + ' ' + tuple[1] + ' is ' + tuple[2]; - * }); - * // -> ['Jane Doe is 23', 'Nitin Patel is 41', 'Guy Forcier is 17'] - **/ - function zip() { - var iterator = Prototype.K, args = $A(arguments); - if (Object.isFunction(args.last())) - iterator = args.pop(); - - var collections = [this].concat(args).map($A); - return this.map(function(value, index) { - return iterator(collections.pluck(index)); - }); - } - - /** - * Enumerable#size() -> Number - * - * Returns the size of the enumeration. - **/ - function size() { - return this.toArray().length; - } - - /** - * Enumerable#inspect() -> String - * - * Returns the debug-oriented string representation of the object. - **/ - function inspect() { - return '#'; - } - - /** alias of: Enumerable#collect - * Enumerable#map([iterator = Prototype.K[, context]]) -> Array - **/ - - /** alias of: Enumerable#any - * Enumerable#some([iterator = Prototype.K[, context]]) -> Boolean - **/ - - /** alias of: Enumerable#all - * Enumerable#every([iterator = Prototype.K[, context]]) -> Boolean - **/ - - /** alias of: Enumerable#findAll - * Enumerable#select(iterator[, context]) -> Array - **/ - - /** alias of: Enumerable#findAll - * Enumerable#filter(iterator[, context]) -> Array - **/ - - /** alias of: Enumerable#include - * Enumerable#member(object) -> Boolean - **/ - - /** alias of: Enumerable#toArray - * Enumerable#entries() -> Array - **/ - - /** alias of: Enumerable#detect - * Enumerable#find(iterator[, context]) -> firstElement | undefined - **/ - - return { - each: each, - eachSlice: eachSlice, - all: all, - every: all, - any: any, - some: any, - collect: collect, - map: collect, - detect: detect, - findAll: findAll, - select: findAll, - filter: findAll, - grep: grep, - include: include, - member: include, - inGroupsOf: inGroupsOf, - inject: inject, - invoke: invoke, - max: max, - min: min, - partition: partition, - pluck: pluck, - reject: reject, - sortBy: sortBy, - toArray: toArray, - entries: toArray, - zip: zip, - size: size, - inspect: inspect, - find: detect - }; -})(); diff --git a/src/prototype/lang/function.js b/src/prototype/lang/function.js deleted file mode 100644 index 508e36fd6..000000000 --- a/src/prototype/lang/function.js +++ /dev/null @@ -1,417 +0,0 @@ -/** section: Language - * class Function - * - * Extensions to the built-in `Function` object. -**/ -Object.extend(Function.prototype, (function() { - var slice = Array.prototype.slice; - - function update(array, args) { - var arrayLength = array.length, length = args.length; - while (length--) array[arrayLength + length] = args[length]; - return array; - } - - function merge(array, args) { - array = slice.call(array, 0); - return update(array, args); - } - - /** - * Function#argumentNames() -> Array - * - * Reads the argument names as stated in the function definition and returns - * the values as an array of strings (or an empty array if the function is - * defined without parameters). - * - * ##### Examples - * - * function fn(foo, bar) { - * return foo + bar; - * } - * fn.argumentNames(); - * //-> ['foo', 'bar'] - * - * Prototype.emptyFunction.argumentNames(); - * //-> [] - **/ - function argumentNames() { - var names = this.toString().match(/^[\s\(]*function[^(]*\(([^)]*)\)/)[1] - .replace(/\/\/.*?[\r\n]|\/\*(?:.|[\r\n])*?\*\//g, '') - .replace(/\s+/g, '').split(','); - return names.length == 1 && !names[0] ? [] : names; - } - - /** related to: Function#bindAsEventListener - * Function#bind(context[, args...]) -> Function - * - context (Object): The object to bind to. - * - args (?): Optional additional arguments to curry for the function. - * - * Binds this function to the given `context` by wrapping it in another - * function and returning the wrapper. Whenever the resulting "bound" - * function is called, it will call the original ensuring that `this` is set - * to `context`. Also optionally curries arguments for the function. - * - * `Function#bind` acts as an ECMAScript 5 [polyfill](http://remysharp.com/2010/10/08/what-is-a-polyfill/). - * It is only defined if not already present in the user's browser, and it - * is meant to behave like the native version as much as possible. Consult - * the [ES5 specification](http://es5.github.com/#x15.3.4.5) for more - * information. - * - * ##### Examples - * - * A typical use of [[Function#bind]] is to ensure that a callback (event - * handler, etc.) that is an object method gets called with the correct - * object as its context (`this` value): - * - * var AlertOnClick = Class.create({ - * initialize: function(msg) { - * this.msg = msg; - * }, - * handleClick: function(event) { - * event.stop(); - * alert(this.msg); - * } - * }); - * var myalert = new AlertOnClick("Clicked!"); - * $('foo').observe('click', myalert.handleClick); // <= WRONG - * // -> If 'foo' is clicked, the alert will be blank; "this" is wrong - * $('bar').observe('click', myalert.handleClick.bind(myalert)); // <= RIGHT - * // -> If 'bar' is clicked, the alert will be "Clicked!" - * - * `bind` can also *curry* (burn in) arguments for the function if you - * provide them after the `context` argument: - * - * var Averager = Class.create({ - * initialize: function() { - * this.count = 0; - * this.total = 0; - * }, - * add: function(addend) { - * ++this.count; - * this.total += addend; - * }, - * getAverage: function() { - * return this.count == 0 ? NaN : this.total / this.count; - * } - * }); - * var a = new Averager(); - * var b = new Averager(); - * var aAdd5 = a.add.bind(a, 5); // Bind to a, curry 5 - * var aAdd10 = a.add.bind(a, 10); // Bind to a, curry 10 - * var bAdd20 = b.add.bind(b, 20); // Bind to b, curry 20 - * aAdd5(); - * aAdd10(); - * bAdd20(); - * bAdd20(); - * alert(a.getAverage()); - * // -> Alerts "7.5" (average of [5, 10]) - * alert(b.getAverage()); - * // -> Alerts "20" (average of [20, 20]) - * - * (To curry without binding, see [[Function#curry]].) - **/ - - function bind(context) { - if (arguments.length < 2 && Object.isUndefined(arguments[0])) - return this; - - if (!Object.isFunction(this)) - throw new TypeError("The object is not callable."); - - var nop = function() {}; - var __method = this, args = slice.call(arguments, 1); - - var bound = function() { - var a = merge(args, arguments); - // Ignore the supplied context when the bound function is called with - // the "new" keyword. - var c = this instanceof bound ? this : context; - return __method.apply(c, a); - }; - - nop.prototype = this.prototype; - bound.prototype = new nop(); - - return bound; - } - - /** related to: Function#bind - * Function#bindAsEventListener(context[, args...]) -> Function - * - context (Object): The object to bind to. - * - args (?): Optional arguments to curry after the event argument. - * - * An event-specific variant of [[Function#bind]] which ensures the function - * will recieve the current event object as the first argument when - * executing. - * - * It is not necessary to use `bindAsEventListener` for all bound event - * handlers; [[Function#bind]] works well for the vast majority of cases. - * `bindAsEventListener` is only needed when: - * - * - Using old-style DOM0 handlers rather than handlers hooked up via - * [[Event.observe]], because `bindAsEventListener` gets the event object - * from the right place (even on MSIE). (If you're using `Event.observe`, - * that's already handled.) - * - You want to bind an event handler and curry additional arguments but - * have those arguments appear after, rather than before, the event object. - * This mostly happens if the number of arguments will vary, and so you - * want to know the event object is the first argument. - * - * ##### Example - * - * var ContentUpdater = Class.create({ - * initialize: function(initialData) { - * this.data = Object.extend({}, initialData); - * }, - * // On an event, update the content in the elements whose - * // IDs are passed as arguments from our data - * updateTheseHandler: function(event) { - * var argIndex, id, element; - * event.stop(); - * for (argIndex = 1; argIndex < arguments.length; ++argIndex) { - * id = arguments[argIndex]; - * element = $(id); - * if (element) { - * element.update(String(this.data[id]).escapeHTML()); - * } - * } - * } - * }); - * var cu = new ContentUpdater({ - * dispName: 'Joe Bloggs', - * dispTitle: 'Manager ', - * dispAge: 47 - * }); - * // Using bindAsEventListener because of the variable arg lists: - * $('btnUpdateName').observe('click', - * cu.updateTheseHandler.bindAsEventListener(cu, 'dispName') - * ); - * $('btnUpdateAll').observe('click', - * cu.updateTheseHandler.bindAsEventListener(cu, 'dispName', 'dispTitle', 'dispAge') - * ); - **/ - function bindAsEventListener(context) { - var __method = this, args = slice.call(arguments, 1); - return function(event) { - var a = update([event || window.event], args); - return __method.apply(context, a); - } - } - - /** - * Function#curry(args...) -> Function - * - args (?): The arguments to curry. - * - * *Curries* (burns in) arguments to a function, returning a new function - * that when called with call the original passing in the curried arguments - * (along with any new ones): - * - * function showArguments() { - * alert($A(arguments).join(', ')); - * } - * showArguments(1, 2,, 3); - * // -> alerts "1, 2, 3" - * - * var f = showArguments.curry(1, 2, 3); - * f('a', 'b'); - * // -> alerts "1, 2, 3, a, b" - * - * [[Function#curry]] works just like [[Function#bind]] without the initial - * context argument. Use `bind` if you need to curry arguments _and_ set - * context at the same time. - * - * The name "curry" comes from [mathematics](http://en.wikipedia.org/wiki/Currying). - **/ - function curry() { - if (!arguments.length) return this; - var __method = this, args = slice.call(arguments, 0); - return function() { - var a = merge(args, arguments); - return __method.apply(this, a); - } - } - - /** - * Function#delay(timeout[, args...]) -> Number - * - timeout (Number): The time, in seconds, to wait before calling the - * function. - * - args (?): Optional arguments to pass to the function when calling it. - * - * Schedules the function to run after the specified amount of time, passing - * any arguments given. - * - * Behaves much like `window.setTimeout`, but the timeout is in seconds - * rather than milliseconds. Returns an integer ID that can be used to - * clear the timeout with `window.clearTimeout` before it runs. - * - * To schedule a function to run as soon as the interpreter is idle, use - * [[Function#defer]]. - * - * ##### Example - * - * function showMsg(msg) { - * alert(msg); - * } - * showMsg.delay(0.1, "Hi there!"); - * // -> Waits a 10th of a second, then alerts "Hi there!" - **/ - function delay(timeout) { - var __method = this, args = slice.call(arguments, 1); - timeout = timeout * 1000; - return window.setTimeout(function() { - return __method.apply(__method, args); - }, timeout); - } - - /** - * Function#defer(args...) -> Number - * - args (?): Optional arguments to pass into the function. - * - * Schedules the function to run as soon as the interpreter is idle. - * - * A "deferred" function will not run immediately; rather, it will run as soon - * as the interpreter's call stack is empty. - * - * Behaves much like `window.setTimeout` with a delay set to `0`. Returns an - * ID that can be used to clear the timeout with `window.clearTimeout` before - * it runs. - * - * ##### Example - * - * function showMsg(msg) { - * alert(msg); - * } - * - * showMsg("One"); - * showMsg.defer("Two"); - * showMsg("Three"); - * // Alerts "One", then "Three", then (after a brief pause) "Two" - * // Note that "Three" happens before "Two" - **/ - function defer() { - var args = update([0.01], arguments); - return this.delay.apply(this, args); - } - - /** - * Function#wrap(wrapper) -> Function - * - wrapper (Function): The function to use as a wrapper. - * - * Returns a function "wrapped" around the original function. - * - * [[Function#wrap]] distills the essence of aspect-oriented programming into - * a single method, letting you easily build on existing functions by - * specifying before and after behavior, transforming the return value, or - * even preventing the original function from being called. - * - * The wrapper function is called with this signature: - * - * function wrapper(callOriginal[, args...]) - * - * ...where `callOriginal` is a function that can be used to call the - * original (wrapped) function (or not, as appropriate). (`callOriginal` is - * not a direct reference to the original function, there's a layer of - * indirection in-between that sets up the proper context \[`this` value\] for - * it.) - * - * ##### Example - * - * // Wrap String#capitalize so it accepts an additional argument - * String.prototype.capitalize = String.prototype.capitalize.wrap( - * function(callOriginal, eachWord) { - * if (eachWord && this.include(" ")) { - * // capitalize each word in the string - * return this.split(" ").invoke("capitalize").join(" "); - * } else { - * // proceed using the original function - * return callOriginal(); - * } - * }); - * - * "hello world".capitalize(); - * // -> "Hello world" (only the 'H' is capitalized) - * "hello world".capitalize(true); - * // -> "Hello World" (both 'H' and 'W' are capitalized) - **/ - function wrap(wrapper) { - var __method = this; - return function() { - var a = update([__method.bind(this)], arguments); - return wrapper.apply(this, a); - } - } - - /** - * Function#methodize() -> Function - * - * Wraps the function inside another function that, when called, pushes - * `this` to the original function as the first argument (with any further - * arguments following it). - * - * The `methodize` method transforms the original function that has an - * explicit first argument to a function that passes `this` (the current - * context) as an implicit first argument at call time. It is useful when we - * want to transform a function that takes an object to a method of that - * object or its prototype, shortening its signature by one argument. - * - * ##### Example - * - * // A function that sets a name on a target object - * function setName(target, name) { - * target.name = name; - * } - * - * // Use it - * obj = {}; - * setName(obj, 'Fred'); - * obj.name; - * // -> "Fred" - * - * // Make it a method of the object - * obj.setName = setName.methodize(); - * - * // Use the method instead - * obj.setName('Barney'); - * obj.name; - * // -> "Barney" - * - * The example above is quite simplistic. It's more useful to copy methodized - * functions to object prototypes so that new methods are immediately shared - * among instances. In the Prototype library, `methodize` is used in various - * places such as the DOM module, so that (for instance) you can hide an - * element either by calling the static version of `Element.hide` and passing in - * an element reference or ID, like so: - * - * Element.hide('myElement'); - * - * ...or if you already have an element reference, just calling the - * methodized form instead: - * - * myElement.hide(); - **/ - function methodize() { - if (this._methodized) return this._methodized; - var __method = this; - return this._methodized = function() { - var a = update([this], arguments); - return __method.apply(null, a); - }; - } - - var extensions = { - argumentNames: argumentNames, - bindAsEventListener: bindAsEventListener, - curry: curry, - delay: delay, - defer: defer, - wrap: wrap, - methodize: methodize - }; - - if (!Function.prototype.bind) - extensions.bind = bind; - - return extensions; -})()); - diff --git a/src/prototype/lang/hash.js b/src/prototype/lang/hash.js deleted file mode 100644 index 662640fcf..000000000 --- a/src/prototype/lang/hash.js +++ /dev/null @@ -1,408 +0,0 @@ -/** section: Language, related to: Hash - * $H([obj]) -> Hash - * - * Creates a [[Hash]] (which is synonymous to "map" or "associative array" - * for our purposes). A convenience wrapper around the [[Hash]] constructor, with a safeguard - * that lets you pass an existing [[Hash]] object and get it back untouched (instead of - * uselessly cloning it). - * - * The [[$H]] function is the shorter way to obtain a hash (prior to 1.5 final, it was - * the *only* proper way of getting one). - * - * ##### Example - * - * var h = $H({name: 'John', age: 26, country: 'Australia'}); - * // Equivalent to: - * var h = new Hash({name: 'John', age: 26, country: 'Australia'}); - * // Can then be accessed the classic Hash way - * h.get('country'); - * // -> 'Australia' -**/ -function $H(object) { - return new Hash(object); -}; - -/** section: Language - * class Hash - * includes Enumerable - * - * A set of key/value pairs. - * - * [[Hash]] can be thought of as an associative array, binding unique keys to - * values (which are not necessarily unique), though it can not guarantee - * consistent order its elements when iterating. Because of the nature of - * JavaScript, every object is in fact a hash; but [[Hash]] adds a number of - * methods that let you enumerate keys and values, iterate over key/value - * pairs, merge two hashes together, and much more. - * - * ##### Creating a hash - * - * You can create a Hash either via `new Hash()` or the convenience alias - * `$H()`; there is **no** difference between them. In either case, you may - * optionally pass in an object to seed the [[Hash]]. If you pass in a [[Hash]], - * it will be cloned. - * -**/ -var Hash = Class.create(Enumerable, (function() { - /** - * new Hash([object]) - * - * Creates a new [[Hash]]. If `object` is given, the new hash will be populated - * with all the object's properties. See [[$H]]. - **/ - function initialize(object) { - this._object = Object.isHash(object) ? object.toObject() : Object.clone(object); - } - - // Docs for #each even though technically it's implemented by Enumerable - /** - * Hash#each(iterator[, context]) -> Hash - * - iterator (Function): A function that expects each item in the [[Hash]] - * as the first argument and a numerical index as the second. - * - context (Object): The scope in which to call `iterator`. Determines what - * `this` means inside `iterator`. - * - * Iterates over the name/value pairs in the hash. - * - * This is actually just the [[Enumerable#each #each]] method from the - * mixed-in [[Enumerable]] module. It is documented here to describe the - * structure of the elements passed to the iterator and the order of - * iteration. - * - * The iterator's first argument (the "item") is an object with two - * properties: - * - * - `key`: the key name as a `String` - * - `value`: the corresponding value (which may be `undefined`) - * - * The order of iteration is implementation-dependent, as it relies on - * the order of the native `for..in` loop. Although most modern - * implementations exhibit *ordered* behavior, this is not standardized and - * may not always be the case, and so cannot be relied upon. - * - * ##### Example - * - * var h = $H({version: 1.6, author: 'The Core Team'}); - * - * h.each(function(pair) { - * alert(pair.key + ' = "' + pair.value + '"'); - * }); - * // Alerts 'version = "1.6"' and 'author = "The Core Team"' - * // -or- - * // Alerts 'author = "The Core Team"' and 'version = "1.6"' - **/ - - // Our _internal_ each - function _each(iterator, context) { - var i = 0; - for (var key in this._object) { - var value = this._object[key], pair = [key, value]; - pair.key = key; - pair.value = value; - iterator.call(context, pair, i); - i++; - } - } - - /** - * Hash#set(key, value) -> value - * - key (String): The key to use for this value. - * - value (?): The value to use for this key. - * - * Stores `value` in the hash using the key `key` and returns `value`. - * - * ##### Example - * - * var h = $H(); - * h.keys(); - * // -> [] (initially empty) - * h.set('a', 'apple'); - * // -> "apple" - * h.keys(); - * // -> ["a"] (has the new entry) - * h.get('a'); - * // -> "apple" - **/ - function set(key, value) { - return this._object[key] = value; - } - - /** - * Hash#get(key) -> value - * - * Returns the stored value for the given `key`. - * - * ##### Examples - * - * var h = new Hash({a: 'apple', b: 'banana', c: 'coconut'}); - * h.get('a'); - * // -> 'apple' - **/ - function get(key) { - // simulating poorly supported hasOwnProperty - if (this._object[key] !== Object.prototype[key]) - return this._object[key]; - } - - /** - * Hash#unset(key) -> value - * - * Deletes the stored pair for the given `key` from the hash and returns its - * value. - * - * ##### Example - * - * var h = new Hash({a: 'apple', b: 'banana', c: 'coconut'}); - * h.keys(); - * // -> ["a", "b", "c"] - * h.unset('a'); - * // -> 'apple' - * h.keys(); - * // -> ["b", "c"] ("a" is no longer in the hash) - **/ - function unset(key) { - var value = this._object[key]; - delete this._object[key]; - return value; - } - - /** - * Hash#toObject() -> Object - * - * Returns a cloned, vanilla object whose properties (and property values) - * match the keys (and values) from the hash. - * - * ##### Example - * - * var h = new Hash({ a: 'apple', b: 'banana', c: 'coconut' }); - * var obj = h.toObject(); - * obj.a; - * // -> "apple" - **/ - function toObject() { - return Object.clone(this._object); - } - - /** related to: Object.toJSON, alias of: Hash#toObject - * Hash#toJSON() -> Object - **/ - - /** alias of: Hash#toObject - * Hash#toTemplateReplacements() -> Object - **/ - - /** - * Hash#keys() -> [String...] - * - * Provides an Array containing the keys for items stored in the hash. - * - * The order of the keys is not guaranteed. - * - * ##### Example - * - * var h = $H({one: "uno", two: "due", three: "tre"}); - * h.keys(); - * // -> ["one", "three", "two"] (these may be in any order) - **/ - function keys() { - return this.pluck('key'); - } - - /** - * Hash#values() -> Array - * - * Collects the values of the hash and returns them in an array. - * - * The order of the values is not guaranteed. - * - * ##### Example - * - * var h = $H({one: "uno", two: "due", three: "tre"}); - * h.values(); - * // -> ["uno", "tre", "due"] (these may be in any order) - **/ - function values() { - return this.pluck('value'); - } - - /** - * Hash#index(value) -> String - * - * Returns the first key in the hash whose value matches `value`. - * Returns `false` if there is no such key. - **/ - function index(value) { - var match = this.detect(function(pair) { - return pair.value === value; - }); - return match && match.key; - } - - /** - * Hash#merge(object) -> Hash - * - object (Object | Hash): The object to merge with this hash to produce - * the resulting hash. - * - * Returns a new [[Hash]] instance with `object`'s key/value pairs merged in; - * this hash remains unchanged. - * - * To modify the original hash in place, use [[Hash#update]]. - * - * ##### Example - * - * var h = $H({one: "uno", two: "due"}); - * var h2 = h.merge({three: "tre"}); - * h.keys(); - * // -> ["one", "two"] (unchanged) - * h2.keys(); - * // -> ["one", "two", "three"] (has merged contents) - **/ - function merge(object) { - return this.clone().update(object); - } - - /** - * Hash#update(object) -> Hash - * - object (Object | Hash): The object to merge with this hash to produce - * the resulting hash. - * - * Updates a hash *in place* with the key/value pairs of `object`, returns - * the hash. - * - * [[Hash#update]] modifies the hash. To get a new hash instead, use - * [[Hash#merge]]. - * - * ##### Example - * - * var h = $H({one: "uno", two: "due"}); - * h.update({three: "tre"}); - * // -> h (a reference to the original hash) - * h.keys(); - * // -> ["one", "two", "three"] (has merged contents) - **/ - function update(object) { - return new Hash(object).inject(this, function(result, pair) { - result.set(pair.key, pair.value); - return result; - }); - } - - // Private. No PDoc necessary. - function toQueryPair(key, value) { - if (Object.isUndefined(value)) return key; - - value = String.interpret(value); - - // Normalize newlines as \r\n because the HTML spec says newlines should - // be encoded as CRLFs. - value = value.gsub(/(\r)?\n/, '\r\n'); - value = encodeURIComponent(value); - // Likewise, according to the spec, spaces should be '+' rather than - // '%20'. - value = value.gsub(/%20/, '+'); - return key + '=' + value; - } - - /** related to: String#toQueryParams - * Hash#toQueryString() -> String - * - * Returns a URL-encoded string containing the hash's contents as query - * parameters according to the following rules: - * - * - An undefined value results a parameter with no value portion at all - * (simply the key name, no equal sign). - * - A null value results a parameter with a blank value (the key followed - * by an equal sign and nothing else). - * - A boolean value results a parameter with the value "true" or "false". - * - An Array value results in a parameter for each array element, in - * array order, each using the same key. - * - All keys and values are URI-encoded using JavaScript's native - * `encodeURIComponent` function. - * - * The order of pairs in the string is not guaranteed, other than the order - * of array values described above. - * - * ##### Example - * - * $H({action: 'ship', - * order_id: 123, - * fees: ['f1', 'f2'] - * }).toQueryString(); - * // -> "action=ship&order_id=123&fees=f1&fees=f2" - * - * $H({comment: '', - * 'key with spaces': true, - * related_order: undefined, - * contents: null, - * 'label': 'a demo' - * }).toQueryString(); - * // -> "comment=&key%20with%20spaces=true&related_order&contents=&label=a%20demo" - * - * // an empty hash is an empty query string: - * $H().toQueryString(); - * // -> "" - **/ - function toQueryString() { - return this.inject([], function(results, pair) { - var key = encodeURIComponent(pair.key), values = pair.value; - - if (values && typeof values == 'object') { - if (Object.isArray(values)) { - // We used to use `Array#map` here to get the query pair for each - // item in the array, but that caused test regressions once we - // added the sparse array behavior for array iterator methods. - // Changed to an ordinary `for` loop so that we can handle - // `undefined` values ourselves rather than have them skipped. - var queryValues = []; - for (var i = 0, len = values.length, value; i < len; i++) { - value = values[i]; - queryValues.push(toQueryPair(key, value)); - } - return results.concat(queryValues); - } - } else results.push(toQueryPair(key, values)); - return results; - }).join('&'); - } - - /** related to: Object.inspect - * Hash#inspect() -> String - * - * Returns the debug-oriented string representation of the Hash. - **/ - function inspect() { - return '#'; - } - - /** - * Hash#clone() -> Hash - * - * Returns a clone of this [[Hash]]. - **/ - function clone() { - return new Hash(this); - } - - return { - initialize: initialize, - _each: _each, - set: set, - get: get, - unset: unset, - toObject: toObject, - toTemplateReplacements: toObject, - keys: keys, - values: values, - index: index, - merge: merge, - update: update, - toQueryString: toQueryString, - inspect: inspect, - toJSON: toObject, - clone: clone - }; -})()); - -Hash.from = $H; diff --git a/src/prototype/lang/number.js b/src/prototype/lang/number.js deleted file mode 100644 index f6acbc8de..000000000 --- a/src/prototype/lang/number.js +++ /dev/null @@ -1,158 +0,0 @@ -/** section: Language - * class Number - * - * Extensions to the built-in `Number` object. - * - * Prototype extends native JavaScript numbers in order to provide: - * - * * [[ObjectRange]] compatibility, through [[Number#succ]]. - * * Numerical loops with [[Number#times]]. - * * Simple utility methods such as [[Number#toColorPart]] and - * [[Number#toPaddedString]]. - * * Instance-method aliases of many functions in the `Math` namespace. - * -**/ -Object.extend(Number.prototype, (function() { - /** - * Number#toColorPart() -> String - * - * Produces a 2-digit hexadecimal representation of the number - * (which is therefore assumed to be in the \[0..255\] range, inclusive). - * Useful for composing CSS color strings. - * - * ##### Example - * - * 10.toColorPart() - * // -> "0a" - **/ - function toColorPart() { - return this.toPaddedString(2, 16); - } - - /** - * Number#succ() -> Number - * - * Returns the successor of the current [[Number]], as defined by current + 1. - * Used to make numbers compatible with [[ObjectRange]]. - **/ - function succ() { - return this + 1; - } - - /** - * Number#times(iterator[,context]) -> Number - * - iterator (Function): An iterator function to call. - * - context (Object): An optional context (`this` value) to use when - * calling `iterator`. - * - * Calls `iterator` the specified number of times, passing in a number as - * the first parameter. The number will be 0 on first call, 1 on second - * call, etc. `times` returns the number instance it was called on. - * - * ##### Example - * - * (3).times(alert); - * // -> Alerts "0", then "1", then "2"; returns 3 - * - * var obj = {count: 0, total: 0}; - * function add(addend) { - * ++this.count; - * this.total += addend; - * } - * (4).times(add, obj); - * // -> 4 - * obj.count; - * // -> 4 - * obj.total; - * // -> 6 (e.g., 0 + 1 + 2 + 3) - **/ - function times(iterator, context) { - $R(0, this, true).each(iterator, context); - return this; - } - - /** - * Number#toPaddedString(length[, radix]) -> String - * - length (Number): The minimum length for the resulting string. - * - radix (Number): An optional radix for the string representation, - * defaults to 10 (decimal). - * - * Returns a string representation of the number padded with leading 0s so - * that the string's length is at least equal to `length`. Takes an optional - * `radix` argument which specifies the base to use for conversion. - * - * ##### Examples - * - * (13).toPaddedString(4); - * // -> "0013" - * - * (13).toPaddedString(2); - * // -> "13" - * - * (13).toPaddedString(1); - * // -> "13" - * - * (13).toPaddedString(4, 16) - * // -> "000d" - * - * (13).toPaddedString(4, 2); - * // -> "1101" - **/ - function toPaddedString(length, radix) { - var string = this.toString(radix || 10); - return '0'.times(length - string.length) + string; - } - - /** - * Number#abs() -> Number - * - * Returns the absolute value of the number. Convenience method that simply - * calls `Math.abs` on this instance and returns the result. - **/ - function abs() { - return Math.abs(this); - } - - /** - * Number#round() -> Number - * - * Rounds the number to the nearest integer. Convenience method that simply - * calls `Math.round` on this instance and returns the result. - **/ - function round() { - return Math.round(this); - } - - /** - * Number#ceil() -> Number - * - * Returns the smallest integer greater than or equal to the number. - * Convenience method that simply calls `Math.ceil` on this instance and - * returns the result. - **/ - function ceil() { - return Math.ceil(this); - } - - /** - * Number#floor() -> Number - * - * Returns the largest integer less than or equal to the number. - * Convenience method that simply calls `Math.floor` on this instance and - * returns the result. - **/ - function floor() { - return Math.floor(this); - } - - return { - toColorPart: toColorPart, - succ: succ, - times: times, - toPaddedString: toPaddedString, - abs: abs, - round: round, - ceil: ceil, - floor: floor - }; -})()); diff --git a/src/prototype/lang/object.js b/src/prototype/lang/object.js deleted file mode 100644 index 47fba60fd..000000000 --- a/src/prototype/lang/object.js +++ /dev/null @@ -1,537 +0,0 @@ -/** section: Language - * class Object - * - * Extensions to the built-in [[Object]] object. - * - * Because it is dangerous and invasive to augment `Object.prototype` (i.e., - * add instance methods to objects), all these methods are static methods that - * take an [[Object]] as their first parameter. - * - * [[Object]] is used by Prototype as a namespace; that is, it just keeps a few - * new methods together, which are intended for namespaced access (i.e. starting - * with "`Object.`"). - * - * For the regular developer (who simply uses Prototype without tweaking it), the - * most commonly used methods are probably [[Object.inspect]] and, to a lesser degree, - * [[Object.clone]]. - * - * Advanced users, who wish to create their own objects like Prototype does, or - * explore objects as if they were hashes, will turn to [[Object.extend]], - * [[Object.keys]], and [[Object.values]]. -**/ -(function() { - - var _toString = Object.prototype.toString, - NULL_TYPE = 'Null', - UNDEFINED_TYPE = 'Undefined', - BOOLEAN_TYPE = 'Boolean', - NUMBER_TYPE = 'Number', - STRING_TYPE = 'String', - OBJECT_TYPE = 'Object', - FUNCTION_CLASS = '[object Function]', - BOOLEAN_CLASS = '[object Boolean]', - NUMBER_CLASS = '[object Number]', - STRING_CLASS = '[object String]', - ARRAY_CLASS = '[object Array]', - DATE_CLASS = '[object Date]'; - - function Type(o) { - switch(o) { - case null: return NULL_TYPE; - case (void 0): return UNDEFINED_TYPE; - } - var type = typeof o; - switch(type) { - case 'boolean': return BOOLEAN_TYPE; - case 'number': return NUMBER_TYPE; - case 'string': return STRING_TYPE; - } - return OBJECT_TYPE; - } - - /** - * Object.extend(destination, source) -> Object - * - destination (Object): The object to receive the new properties. - * - source (Object): The object whose properties will be duplicated. - * - * Copies all properties from the source to the destination object. Used by Prototype - * to simulate inheritance (rather statically) by copying to prototypes. - * - * Documentation should soon become available that describes how Prototype implements - * OOP, where you will find further details on how Prototype uses [[Object.extend]] and - * [[Class.create]] (something that may well change in version 2.0). It will be linked - * from here. - * - * Do not mistake this method with its quasi-namesake [[Element.extend]], - * which implements Prototype's (much more complex) DOM extension mechanism. - **/ - function extend(destination, source) { - for (var property in source) - destination[property] = source[property]; - return destination; - } - - /** - * Object.inspect(obj) -> String - * - object (Object): The item to be inspected. - * - * Returns the debug-oriented string representation of the object. - * - * * `undefined` and `null` are represented as such. - * * Other types are looked up for a `inspect` method: if there is one, it is used, otherwise, - * it reverts to the `toString` method. - * - * Prototype provides `inspect` methods for many types, both built-in and library-defined, - * such as in [[String#inspect]], [[Array#inspect]], [[Enumerable#inspect]] and [[Hash#inspect]], - * which attempt to provide most-useful string representations (from a developer's standpoint) - * for their respective types. - * - * ##### Examples - * - * Object.inspect(); - * // -> 'undefined' - * - * Object.inspect(null); - * // -> 'null' - * - * Object.inspect(false); - * // -> 'false' - * - * Object.inspect([1, 2, 3]); - * // -> '[1, 2, 3]' - * - * Object.inspect('hello'); - * // -> "'hello'" - **/ - function inspect(object) { - try { - if (isUndefined(object)) return 'undefined'; - if (object === null) return 'null'; - return object.inspect ? object.inspect() : String(object); - } catch (e) { - if (e instanceof RangeError) return '...'; - throw e; - } - } - - /** - * Object.toJSON(object) -> String - * - object (Object): The object to be serialized. - * - * Returns a JSON string. - * - * `undefined` and `function` types have no JSON representation. `boolean` - * and `null` are coerced to strings. - * - * For other types, [[Object.toJSON]] looks for a `toJSON` method on `object`. - * If there is one, it is used; otherwise the object is treated like a - * generic [[Object]]. - * - * For more information on Prototype's JSON encoder, hop to our - * [tutorial](http://prototypejs.org/learn/json). - * - * ##### Example - * - * var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']}; - * Object.toJSON(data); - * //-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}' - **/ - function toJSON(value) { - return JSON.stringify(value); - } - - function Str(key, holder, stack) { - var value = holder[key]; - if (Type(value) === OBJECT_TYPE && typeof value.toJSON === 'function') { - value = value.toJSON(key); - } - - var _class = _toString.call(value); - - switch (_class) { - case NUMBER_CLASS: - case BOOLEAN_CLASS: - case STRING_CLASS: - value = value.valueOf(); - } - - switch (value) { - case null: return 'null'; - case true: return 'true'; - case false: return 'false'; - } - - var type = typeof value; - switch (type) { - case 'string': - return value.inspect(true); - case 'number': - return isFinite(value) ? String(value) : 'null'; - case 'object': - - for (var i = 0, length = stack.length; i < length; i++) { - if (stack[i] === value) { - throw new TypeError("Cyclic reference to '" + value + "' in object"); - } - } - stack.push(value); - - var partial = []; - if (_class === ARRAY_CLASS) { - for (var i = 0, length = value.length; i < length; i++) { - var str = Str(i, value, stack); - partial.push(typeof str === 'undefined' ? 'null' : str); - } - partial = '[' + partial.join(',') + ']'; - } else { - var keys = Object.keys(value); - for (var i = 0, length = keys.length; i < length; i++) { - var key = keys[i], str = Str(key, value, stack); - if (typeof str !== "undefined") { - partial.push(key.inspect(true)+ ':' + str); - } - } - partial = '{' + partial.join(',') + '}'; - } - stack.pop(); - return partial; - } - } - - /** - * Object.toQueryString(object) -> String - * - object (Object): The object whose property/value pairs will be converted. - * - * Turns an object into its URL-encoded query string representation. - * - * This is a form of serialization, and is mostly useful to provide complex - * parameter sets for stuff such as objects in the [[Ajax]] namespace (e.g. - * [[Ajax.Request]]). - * - * Undefined-value pairs will be serialized as if empty-valued. Array-valued - * pairs will get serialized with one name/value pair per array element. All - * values get URI-encoded using JavaScript's native `encodeURIComponent` - * function. - * - * The order of pairs in the serialized form is not guaranteed (and mostly - * irrelevant anyway) — except for array-based parts, which are serialized - * in array order. - * - * ##### Examples - * - * Object.toQueryString({ action: 'ship', order_id: 123, fees: ['f1', 'f2'], 'label': 'a demo' }) - * // -> 'action=ship&order_id=123&fees=f1&fees=f2&label=a+demo' - **/ - function toQueryString(object) { - return $H(object).toQueryString(); - } - - /** - * Object.toHTML(object) -> String - * - object (Object): The object to convert to HTML. - * - * Converts the object to its HTML representation. - * - * Returns the return value of `object`'s `toHTML` method if it exists; else - * runs `object` through [[String.interpret]]. - * - * ##### Examples - * - * var Bookmark = Class.create({ - * initialize: function(name, url) { - * this.name = name; - * this.url = url; - * }, - * - * toHTML: function() { - * return '#{name}'.interpolate(this); - * } - * }); - * - * var api = new Bookmark('Prototype API', 'http://prototypejs.org/api'); - * - * Object.toHTML(api); - * //-> 'Prototype API' - * - * Object.toHTML("Hello world!"); - * //-> "Hello world!" - * - * Object.toHTML(); - * //-> "" - * - * Object.toHTML(null); - * //-> "" - * - * Object.toHTML(undefined); - * //-> "" - * - * Object.toHTML(true); - * //-> "true" - * - * Object.toHTML(false); - * //-> "false" - * - * Object.toHTML(123); - * //-> "123" - **/ - function toHTML(object) { - return object && object.toHTML ? object.toHTML() : String.interpret(object); - } - - /** - * Object.values(object) -> Array - * - object (Object): The object to pull values from. - * - * Returns an array of the object's property values. - * - * Note that the order of the resulting array is browser-dependent — it - * relies on the `for...in` loop, for which the ECMAScript spec does not - * prescribe an enumeration order. - * - * Also, remember that while property _names_ are unique, property _values_ - * have no such constraint. - * - * ##### Examples - * - * Object.values(); - * // -> [] - * - * Object.values({ name: 'Prototype', version: '1.6.1' }).sort(); - * // -> ['1.6.1', 'Prototype'] - **/ - function values(object) { - var results = []; - for (var property in object) - results.push(object[property]); - return results; - } - - /** - * Object.clone(object) -> Object - * - object (Object): The object to clone. - * - * Creates and returns a shallow duplicate of the passed object by copying - * all of the original's key/value pairs onto an empty object. - * - * Do note that this is a _shallow_ copy, not a _deep_ copy. Nested objects - * will retain their references. - * - * ##### Examples - * - * var original = {name: 'primaryColors', values: ['red', 'green', 'blue']}; - * var copy = Object.clone(original); - * - * original.name; - * // -> "primaryColors" - * original.values[0]; - * // -> "red" - * copy.name; - * // -> "primaryColors" - * - * copy.name = "secondaryColors"; - * original.name; - * // -> "primaryColors" - * copy.name; - * // -> "secondaryColors" - * - * copy.values[0] = 'magenta'; - * copy.values[1] = 'cyan'; - * copy.values[2] = 'yellow'; - * original.values[0]; - * // -> "magenta" (it's a shallow copy, so they share the array) - **/ - function clone(object) { - return extend({ }, object); - } - - /** - * Object.isElement(object) -> Boolean - * - object (Object): The object to test. - * - * Returns `true` if `object` is a DOM node of type 1; `false` otherwise. - * - * ##### Examples - * - * Object.isElement(new Element('div')); - * //-> true - * - * Object.isElement(document.createElement('div')); - * //-> true - * - * Object.isElement($('id_of_an_exiting_element')); - * //-> true - * - * Object.isElement(document.createTextNode('foo')); - * //-> false - **/ - function isElement(object) { - return !!(object && object.nodeType == 1); - } - - /** - * Object.isArray(object) -> Boolean - * - object (Object): The object to test. - * - * Returns `true` if `object` is an [[Array]]; `false` otherwise. - * - * ##### Examples - * - * Object.isArray([]); - * //-> true - * - * Object.isArray($w()); - * //-> true - * - * Object.isArray({ }); - * //-> false - **/ - var isArray = Array.isArray; - - /** - * Object.isHash(object) -> Boolean - * - object (Object): The object to test. - * - * Returns `true` if `object` is an instance of the [[Hash]] class; `false` - * otherwise. - * - * ##### Examples - * - * Object.isHash(new Hash({ })); - * //-> true - * - * Object.isHash($H({ })); - * //-> true - * - * Object.isHash({ }); - * //-> false - **/ - function isHash(object) { - return object instanceof Hash; - } - - /** - * Object.isFunction(object) -> Boolean - * - object (Object): The object to test. - * - * Returns `true` if `object` is of type [[Function]]; `false` otherwise. - * - * ##### Examples - * - * Object.isFunction($); - * //-> true - * - * Object.isFunction(123); - * //-> false - **/ - function isFunction(object) { - return _toString.call(object) === FUNCTION_CLASS; - } - - /** - * Object.isString(object) -> Boolean - * - object (Object): The object to test. - * - * Returns `true` if `object` is of type [[String]]; `false` otherwise. - * - * ##### Examples - * - * Object.isString("foo"); - * //-> true - * - * Object.isString(""); - * //-> true - * - * Object.isString(123); - * //-> false - **/ - function isString(object) { - return _toString.call(object) === STRING_CLASS; - } - - /** - * Object.isNumber(object) -> Boolean - * - object (Object): The object to test. - * - * Returns `true` if `object` is of type [[Number]]; `false` otherwise. - * - * ##### Examples - * - * Object.isNumber(0); - * //-> true - * - * Object.isNumber(1.2); - * //-> true - * - * Object.isNumber("foo"); - * //-> false - **/ - function isNumber(object) { - return _toString.call(object) === NUMBER_CLASS; - } - - /** - * Object.isDate(object) -> Boolean - * - object (Object): The object to test. - * - * Returns `true` if `object` is of type [[Date]]; `false` otherwise. - * - * ##### Examples - * - * Object.isDate(new Date); - * //-> true - * - * Object.isDate("Dec 25, 1995"); - * //-> false - * - * Object.isDate(new Date("Dec 25, 1995")); - * //-> true - **/ - function isDate(object) { - return _toString.call(object) === DATE_CLASS; - } - - /** - * Object.isUndefined(object) -> Boolean - * - object (Object): The object to test. - * - * Returns `true` if `object` is of type `undefined`; `false` otherwise. - * - * ##### Examples - * - * Object.isUndefined(); - * //-> true - * - * Object.isUndefined(undefined); - * //-> true - * - * Object.isUndefined(null); - * //-> false - * - * Object.isUndefined(0); - * //-> false - * - * Object.isUndefined(""); - * //-> false - **/ - function isUndefined(object) { - return typeof object === "undefined"; - } - - extend(Object, { - extend: extend, - inspect: inspect, - toJSON: toJSON, - toQueryString: toQueryString, - toHTML: toHTML, - values: values, - clone: clone, - isArray: isArray, - isElement: isElement, - isHash: isHash, - isFunction: isFunction, - isString: isString, - isNumber: isNumber, - isDate: isDate, - isUndefined: isUndefined - }); -})(); diff --git a/src/prototype/lang/periodical_executer.js b/src/prototype/lang/periodical_executer.js deleted file mode 100644 index 519cabd43..000000000 --- a/src/prototype/lang/periodical_executer.js +++ /dev/null @@ -1,85 +0,0 @@ -/** section: Language - * class PeriodicalExecuter - * - * Oversees the calling of a particular function periodically. - * - * [[PeriodicalExecuter]] shields you from multiple parallel executions of a - * `callback` function, should it take longer than the given interval to - * execute. - * - * This is especially useful if you use one to interact with the user at - * given intervals (e.g. use a prompt or confirm call): this will avoid - * multiple message boxes all waiting to be actioned. - * - * ##### Example - * - * new PeriodicalExecuter(function(pe) { - * if (!confirm('Want me to annoy you again later?')) { - * pe.stop(); - * } - * }, 5); -**/ -var PeriodicalExecuter = Class.create({ - /** - * new PeriodicalExecuter(callback, frequency) - * - callback (Function): the function to be executed at each interval. - * - frequency (Number): the amount of time, in seconds, to wait in between - * callbacks. - * - * Creates a [[PeriodicalExecuter]]. - **/ - initialize: function(callback, frequency) { - this.callback = callback; - this.frequency = frequency; - this.currentlyExecuting = false; - - this.registerCallback(); - }, - - registerCallback: function() { - this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); - }, - - execute: function() { - this.callback(this); - }, - - /** - * PeriodicalExecuter#stop() -> undefined - * - * Stops the periodical executer (there will be no further triggers). - * - * Once a [[PeriodicalExecuter]] is created, it constitues an infinite loop, - * triggering at the given interval until the page unloads. This method lets - * you stop it any time you want. - * - * ##### Example - * - * This will only alert 1, 2 and 3, then the [[PeriodicalExecuter]] stops. - * - * var count = 0; - * new PeriodicalExecuter(function(pe) { - * if (++count > 3) { - * pe.stop(); - * } else { - * alert(count); - * } - * }, 1); - **/ - stop: function() { - if (!this.timer) return; - clearInterval(this.timer); - this.timer = null; - }, - - onTimerEvent: function() { - if (!this.currentlyExecuting) { - try { - this.currentlyExecuting = true; - this.execute(); - } finally { - this.currentlyExecuting = false; - } - } - } -}); diff --git a/src/prototype/lang/range.js b/src/prototype/lang/range.js deleted file mode 100644 index 931542f78..000000000 --- a/src/prototype/lang/range.js +++ /dev/null @@ -1,157 +0,0 @@ -/** section: Language - * class ObjectRange - * includes Enumerable - * - * A succession of values. - * - * An [[ObjectRange]] can model a range of any value that implements a `succ` - * method (which links that value to its "successor"). - * - * Prototype provides such a method for [[Number]] and [[String]], but you - * are (of course) welcome to implement useful semantics in your own objects, - * in order to enable ranges based on them. - * - * [[ObjectRange]] mixes in [[Enumerable]], which makes ranges very versatile. - * It takes care, however, to override the default code for `include`, to - * achieve better efficiency. - * - * While [[ObjectRange]] does provide a constructor, the preferred way to obtain - * a range is to use the [[$R]] utility function, which is strictly equivalent - * (only way more concise to use). - * - * See [[$R]] for more information. -**/ - -/** section: Language - * $R(start, end[, exclusive = false]) -> ObjectRange - * - * Creates a new [[ObjectRange]] object. This method is a convenience wrapper - * around the [[ObjectRange]] constructor, but [[$R]] is the preferred alias. - * - * [[ObjectRange]] instances represent a range of consecutive values, be they - * numerical, textual, or of another type that semantically supports value - * ranges. See the type's documentation for further details, and to discover - * how your own objects can support value ranges. - * - * The [[$R]] function takes exactly the same arguments as the original - * constructor: the **lower and upper bounds** (value of the same, proper - * type), and **whether the upper bound is exclusive** or not. By default, the - * upper bound is inclusive. - * - * ##### Examples - * - * $R(0, 10).include(10) - * // -> true - * - * $A($R(0, 5)).join(', ') - * // -> '0, 1, 2, 3, 4, 5' - * - * $A($R('aa', 'ah')).join(', ') - * // -> 'aa, ab, ac, ad, ae, af, ag, ah' - * - * $R(0, 10, true).include(10) - * // -> false - * - * $R(0, 10, true).each(function(value) { - * // invoked 10 times for value = 0 to 9 - * }); - * - * Note that [[ObjectRange]] mixes in the [[Enumerable]] module: this makes it - * easy to convert a range to an [[Array]] ([[Enumerable]] provides the - * [[Enumerable#toArray]] method, which makes the [[$A]] conversion - * straightforward), or to iterate through values. (Note, however, that getting - * the bounds back will be more efficiently done using the - * [[ObjectRange#start]] and [[ObjectRange#end]] properties than calling the - * [[Enumerable#min]] and [[Enumerable#max]] methods). - * - * ##### Warning - * - * **Be careful with [[String]] ranges**: as described in its [[String#succ]] - * method, it does not use alphabetical boundaries, but goes all the way - * through the character table: - * - * $A($R('a', 'e')) - * // -> ['a', 'b', 'c', 'd', 'e'], no surprise there - * - * $A($R('ax', 'ba')) - * // -> Ouch! Humongous array, starting as ['ax', 'ay', 'az', 'a{', 'a|', 'a}', 'a~'...] - * - * See [[ObjectRange]] for more information. -**/ -function $R(start, end, exclusive) { - return new ObjectRange(start, end, exclusive); -} - -var ObjectRange = Class.create(Enumerable, (function() { - /** - * new ObjectRange(start, end[, exclusive = false]) - * - * Creates a new [[ObjectRange]]. - * - * The `exclusive` argument specifies whether `end` itself is a part of the - * range. - **/ - function initialize(start, end, exclusive) { - /** - * ObjectRange#start -> ? - * - * The lower bounding value of the range. - **/ - this.start = start; - /** - * ObjectRange#end -> ? - * - * The upper bounding value of the range. - **/ - this.end = end; - this.exclusive = exclusive; - } - - function _each(iterator, context) { - var value = this.start, i; - for (i = 0; this.include(value); i++) { - iterator.call(context, value, i); - value = value.succ(); - } - } - - /** - * ObjectRange#include(value) -> Boolean - * - * Determines whether the value is included in the range. - * - * This assumes the values in the range have a valid strict weak ordering - * (have valid semantics for the `<` operator). While [[ObjectRange]] mixes - * in [[Enumerable]], this method overrides the default version of - * [[Enumerable#include]], and is much more efficient (it uses a maximum of - * two comparisons). - * - * ##### Examples - * - * $R(1, 10).include(5); - * // -> true - * - * $R('a', 'h').include('x'); - * // -> false - * - * $R(1, 10).include(10); - * // -> true - * - * $R(1, 10, true).include(10); - * // -> false - **/ - function include(value) { - if (value < this.start) - return false; - if (this.exclusive) - return value < this.end; - return value <= this.end; - } - - return { - initialize: initialize, - _each: _each, - include: include - }; -})()); - diff --git a/src/prototype/lang/regexp.js b/src/prototype/lang/regexp.js deleted file mode 100644 index c1663408b..000000000 --- a/src/prototype/lang/regexp.js +++ /dev/null @@ -1,27 +0,0 @@ -/** section: Language - * class RegExp - * - * Extensions to the built-in `RegExp` object. -**/ - -/** - * RegExp#match(str) -> Boolean - * - str (String): a string against witch to match the regular expression. - * - * Alias of the native `RegExp#test` method. Returns `true` - * if `str` matches the regular expression, `false` otherwise. - **/ -RegExp.prototype.match = RegExp.prototype.test; - -/** - * RegExp.escape(str) -> String - * - str (String): A string intended to be used in a `RegExp` constructor. - * - * Escapes any characters in the string that have special meaning in a - * regular expression. - * - * Use before passing a string into the `RegExp` constructor. -**/ -RegExp.escape = function(str) { - return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1'); -}; diff --git a/src/prototype/lang/string.js b/src/prototype/lang/string.js deleted file mode 100644 index 433a1c0b1..000000000 --- a/src/prototype/lang/string.js +++ /dev/null @@ -1,927 +0,0 @@ -/** section: Language - * class String - * - * Extensions to the built-in `String` class. - * - * Prototype enhances the [[String]] object with a series of useful methods for - * ranging from the trivial to the complex. Tired of stripping trailing - * whitespace? Try [[String#strip]]. Want to replace `replace`? Have a look at - * [[String#sub]] and [[String#gsub]]. Need to parse a query string? We have - * [[String#toQueryParams what you need]]. -**/ -Object.extend(String, { - /** - * String.interpret(value) -> String - * - * Coerces `value` into a string. Returns an empty string for `null`. - **/ - interpret: function(value) { - return value == null ? '' : String(value); - }, - specialChar: { - '\b': '\\b', - '\t': '\\t', - '\n': '\\n', - '\f': '\\f', - '\r': '\\r', - '\\': '\\\\' - } -}); - -Object.extend(String.prototype, (function() { - - function prepareReplacement(replacement) { - if (Object.isFunction(replacement)) return replacement; - var template = new Template(replacement); - return function(match) { return template.evaluate(match) }; - } - - // In some versions of Chrome, an empty RegExp has "(?:)" as a `source` - // property instead of an empty string. - function isNonEmptyRegExp(regexp) { - return regexp.source && regexp.source !== '(?:)'; - } - - - /** - * String#gsub(pattern, replacement) -> String - * - * Returns the string with _every_ occurence of a given pattern replaced by either a - * regular string, the returned value of a function or a [[Template]] string. - * The pattern can be a string or a regular expression. - * - * If its second argument is a string [[String#gsub]] works just like the native JavaScript - * method `replace()` set to global match. - * - * var mouseEvents = 'click dblclick mousedown mouseup mouseover mousemove mouseout'; - * - * mouseEvents.gsub(' ', ', '); - * // -> 'click, dblclick, mousedown, mouseup, mouseover, mousemove, mouseout' - * - * mouseEvents.gsub(/\s+/, ', '); - * // -> 'click, dblclick, mousedown, mouseup, mouseover, mousemove, mouseout' - * - * If you pass it a function, it will be invoked for every occurrence of the pattern - * with the match of the current pattern as its unique argument. Note that this argument - * is the returned value of the `match()` method called on the current pattern. It is - * in the form of an array where the first element is the entire match and every subsequent - * one corresponds to a parenthesis group in the regex. - * - * mouseEvents.gsub(/\w+/, function(match){ return 'on' + match[0].capitalize() }); - * // -> 'onClick onDblclick onMousedown onMouseup onMouseover onMousemove onMouseout' - * - * var markdown = '![a pear](/img/pear.jpg) ![an orange](/img/orange.jpg)'; - * - * markdown.gsub(/!\[(.*?)\]\((.*?)\)/, function(match) { - * return '' + match[1] + ''; - * }); - * // -> 'a pear an orange' - * - * Lastly, you can pass [[String#gsub]] a [[Template]] string in which you can also access - * the returned value of the `match()` method using the ruby inspired notation: `#{0}` - * for the first element of the array, `#{1}` for the second one, and so on. - * So our last example could be easily re-written as: - * - * markdown.gsub(/!\[(.*?)\]\((.*?)\)/, '#{1}'); - * // -> 'a pear an orange' - * - * If you need an equivalent to [[String#gsub]] but without global match set on, try [[String#sub]]. - * - * ##### Note - * - * Do _not_ use the `"g"` flag on the regex as this will create an infinite loop. - **/ - function gsub(pattern, replacement) { - var result = '', source = this, match; - replacement = prepareReplacement(replacement); - - if (Object.isString(pattern)) - pattern = RegExp.escape(pattern); - - if (!(pattern.length || isNonEmptyRegExp(pattern))) { - replacement = replacement(''); - return replacement + source.split('').join(replacement) + replacement; - } - - while (source.length > 0) { - match = source.match(pattern) - if (match && match[0].length > 0) { - result += source.slice(0, match.index); - result += String.interpret(replacement(match)); - source = source.slice(match.index + match[0].length); - } else { - result += source, source = ''; - } - } - return result; - } - - /** - * String#sub(pattern, replacement[, count = 1]) -> String - * - * Returns a string with the _first_ `count` occurrences of `pattern` replaced by either - * a regular string, the returned value of a function or a [[Template]] string. - * `pattern` can be a string or a regular expression. - * - * Unlike [[String#gsub]], [[String#sub]] takes a third optional parameter which specifies - * the number of occurrences of the pattern which will be replaced. - * If not specified, it will default to 1. - * - * Apart from that, [[String#sub]] works just like [[String#gsub]]. - * Please refer to it for a complete explanation. - * - * ##### Examples - * - * var fruits = 'apple pear orange'; - * - * fruits.sub(' ', ', '); - * // -> 'apple, pear orange' - * - * fruits.sub(' ', ', ', 1); - * // -> 'apple, pear orange' - * - * fruits.sub(' ', ', ', 2); - * // -> 'apple, pear, orange' - * - * fruits.sub(/\w+/, function(match){ return match[0].capitalize() + ',' }, 2); - * // -> 'Apple, Pear, orange' - * - * var markdown = '![a pear](/img/pear.jpg) ![an orange](/img/orange.jpg)'; - * - * markdown.sub(/!\[(.*?)\]\((.*?)\)/, function(match) { - * return '' + match[1] + ''; - * }); - * // -> 'a pear ![an orange](/img/orange.jpg)' - * - * markdown.sub(/!\[(.*?)\]\((.*?)\)/, '#{1}'); - * // -> 'a pear ![an orange](/img/orange.jpg)' - * - * ##### Note - * - * Do _not_ use the `"g"` flag on the regex as this will create an infinite loop. - **/ - function sub(pattern, replacement, count) { - replacement = prepareReplacement(replacement); - count = Object.isUndefined(count) ? 1 : count; - - return this.gsub(pattern, function(match) { - if (--count < 0) return match[0]; - return replacement(match); - }); - } - - /** related to: String#gsub - * String#scan(pattern, iterator) -> String - * - * Allows iterating over every occurrence of the given pattern (which can be a - * string or a regular expression). - * Returns the original string. - * - * Internally just calls [[String#gsub]] passing it `pattern` and `iterator` as arguments. - * - * ##### Examples - * - * 'apple, pear & orange'.scan(/\w+/, alert); - * // -> 'apple pear & orange' (and displays 'apple', 'pear' and 'orange' in three successive alert dialogs) - * - * Can be used to populate an array: - * - * var fruits = []; - * 'apple, pear & orange'.scan(/\w+/, function(match) { fruits.push(match[0]) }); - * fruits.inspect() - * // -> ['apple', 'pear', 'orange'] - * - * or even to work on the DOM: - * - * 'failure-message, success-message & spinner'.scan(/(\w|-)+/, Element.toggle) - * // -> 'failure-message, success-message & spinner' (and toggles the visibility of each DOM element) - * - * ##### Note - * - * Do _not_ use the `"g"` flag on the regex as this will create an infinite loop. - **/ - function scan(pattern, iterator) { - this.gsub(pattern, iterator); - return String(this); - } - - /** - * String#truncate([length = 30[, suffix = '...']]) -> String - * - * Truncates a string to given `length` and appends `suffix` to it (indicating - * that it is only an excerpt). - * - * ##### Examples - * - * 'A random sentence whose length exceeds 30 characters.'.truncate(); - * // -> 'A random sentence whose len...' - * - * 'Some random text'.truncate(); - * // -> 'Some random text.' - * - * 'Some random text'.truncate(10); - * // -> 'Some ra...' - * - * 'Some random text'.truncate(10, ' [...]'); - * // -> 'Some [...]' - **/ - function truncate(length, truncation) { - length = length || 30; - truncation = Object.isUndefined(truncation) ? '...' : truncation; - return this.length > length ? - this.slice(0, length - truncation.length) + truncation : String(this); - } - - /** - * String#strip() -> String - * - * Strips all leading and trailing whitespace from a string. - * - * ##### Example - * - * ' hello world! '.strip(); - * // -> 'hello world!' - **/ - function strip() { - return this.replace(/^\s+/, '').replace(/\s+$/, ''); - } - - /** - * String#stripTags() -> String - * - * Strips a string of any HTML tags. - * - * Note that [[String#stripTags]] will only strip HTML 4.01 tags — like - * `div`, `span`, and `abbr`. It _will not_ strip namespace-prefixed tags - * such as `h:table` or `xsl:template`. - * - * Watch out for `'.stripTags(); - * // -> 'a linkalert("hello world!");' - * - * 'a link'.stripScripts().stripTags(); - * // -> 'a link' - **/ - function stripTags() { - return this.replace(/<\w+(\s+("[^"]*"|'[^']*'|[^>])+)?(\/)?>|<\/\w+>/gi, ''); - } - - /** - * String#stripScripts() -> String - * - * Strips a string of things that look like HTML script blocks. - * - * ##### Example - * - * "

    This is a test.End of test

    ".stripScripts(); - * // => "

    This is a test.End of test

    " - * - * ##### Caveat User - * - * Note that the processing [[String#stripScripts]] does is good enough for - * most purposes, but you cannot rely on it for security purposes. If you're - * processing end-user-supplied content, [[String#stripScripts]] is probably - * not sufficiently robust to prevent hack attacks. - **/ - function stripScripts() { - return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); - } - - /** - * String#extractScripts() -> Array - * - * Extracts the content of any `'.extractScripts(); - * // -> ['2 + 2'] - * - * ''.extractScripts(); - * // -> ['2 + 2', 'alert("hello world!")'] - * - * ##### Notes - * - * To evaluate the scripts later on, you can use the following: - * - * var myScripts = ''.extractScripts(); - * // -> ['2 + 2', 'alert("hello world!")'] - * - * var myReturnedValues = myScripts.map(function(script) { - * return eval(script); - * }); - * // -> [4, undefined] (and displays 'hello world!' in the alert dialog) - **/ - function extractScripts() { - var matchAll = new RegExp(Prototype.ScriptFragment, 'img'), - matchOne = new RegExp(Prototype.ScriptFragment, 'im'); - var matchMimeType = new RegExp(Prototype.ExecutableScriptFragment, 'im'); - var matchTypeAttribute = /type=/i; - - var results = []; - (this.match(matchAll) || []).each(function(scriptTag) { - var match = scriptTag.match(matchOne); - var attributes = match[1]; - if (attributes !== '') { - // If the script has a `type` attribute, make sure it has a - // JavaScript MIME-type. If not, ignore it. - attributes = attributes.strip(); - var hasTypeAttribute = (matchTypeAttribute).test(attributes); - var hasMimeType = (matchMimeType).test(attributes); - if (hasTypeAttribute && !hasMimeType) return; - } - results.push(match ? match[2] : ''); - }); - - return results; - } - - /** - * String#evalScripts() -> Array - * - * Evaluates the content of any inline `'.evalScripts(); - * // -> [4] - * - * ''.evalScripts(); - * // -> [4, undefined] (and displays 'hello world!' in the alert dialog) - * - * ##### About `evalScripts`, `var`s, and defining functions - * - * [[String#evalScripts]] evaluates script blocks, but this **does not** mean - * they are evaluated in the global scope. They aren't, they're evaluated in - * the scope of the [[String#evalScripts]] method. This has important - * ramifications for your scripts: - * - * * Anything in your script declared with the `var` keyword will be - * discarded momentarily after evaluation, and will be invisible to any - * other scope. - * * If any ` - - - -
    -
    -
    -
    -

    -
    - - - \ No newline at end of file diff --git a/test/console.html b/test/console.html deleted file mode 100644 index 2b586ee42..000000000 --- a/test/console.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - Prototype Console - - - - - - - - -
    -
    - - -
    - - - diff --git a/test/functional/event.html b/test/functional/event.html deleted file mode 100644 index 4e2d11d3d..000000000 --- a/test/functional/event.html +++ /dev/null @@ -1,340 +0,0 @@ - - - - Prototype functional test file - - - - - - - - -

    Prototype functional tests for the Event module

    - -
    - Log -
    -
    - -

    A basic event test - click here

    -

    click to stop observing the first test

    - -

    click to ensure generic Event methods work on inline handlers

    - - - -

    Scope test - scope of the handler should be this element

    - - - -

    Event object test - should be present as a first argument

    - - - -

    Hijack link test (preventDefault)

    - - - -
    - - -

    Mouse click: - left middle right

    - - - -

    Context menu event (tries to prevent default)

    - - - -

    Event.element() test

    - - - -

    Event.currentTarget test

    - - - -

    Event.findElement() test

    - - - -

    Stop propagation test (bubbling)

    - - - -
    -

    Keyup test - focus on the textarea and type

    - -
    - - - -

    bindAsEventListener() test

    - - - -

    Object.inspect(event) test

    - - - -

    mouseenter test

    - - - -

    Add unload events

    - - - -
    - Event delegation -
      -
    • - Child 1 (click) -
    • -
    • - Child 2 (mouseover) -
    • -
    • - Child 3 (mouseup) -
    • -
    - - Results: - -
      -
    • Test 1
    • -
    • Test 2
    • -
    • Test 3
    • -
    -
    - - - - - - diff --git a/test/unit/browsers.sample.yml b/test/unit/browsers.sample.yml deleted file mode 100644 index 86cb549ad..000000000 --- a/test/unit/browsers.sample.yml +++ /dev/null @@ -1,9 +0,0 @@ -# -# If the test runner doesn't know where your browsers are, you can define -# them here. -# - -browsers: - firefox: C:\Program Files\Mozilla Firefox\firefox.exe - opera: C:\Program Files\Opera\launcher.exe - chrome: C:\Program Files\Google\Chrome\Application\chrome.exe diff --git a/test/unit/config.ru b/test/unit/config.ru deleted file mode 100644 index fbdeac151..000000000 --- a/test/unit/config.ru +++ /dev/null @@ -1,2 +0,0 @@ -require './server' -run UnitTests \ No newline at end of file diff --git a/test/unit/fixtures/content.html b/test/unit/fixtures/content.html deleted file mode 100644 index ee3701d3c..000000000 --- a/test/unit/fixtures/content.html +++ /dev/null @@ -1 +0,0 @@ -Pack my box with five dozen liquor jugs! Oh, how quickly daft jumping zebras vex... \ No newline at end of file diff --git a/test/unit/fixtures/data.json b/test/unit/fixtures/data.json deleted file mode 100644 index d1d0f5cbe..000000000 --- a/test/unit/fixtures/data.json +++ /dev/null @@ -1 +0,0 @@ -{"test": 123} \ No newline at end of file diff --git a/test/unit/fixtures/empty.html b/test/unit/fixtures/empty.html deleted file mode 100644 index e69de29bb..000000000 diff --git a/test/unit/fixtures/hello.js b/test/unit/fixtures/hello.js deleted file mode 100644 index 63d81117b..000000000 --- a/test/unit/fixtures/hello.js +++ /dev/null @@ -1 +0,0 @@ -$("content").update("

    Hello world!

    "); diff --git a/test/unit/fixtures/iframe.html b/test/unit/fixtures/iframe.html deleted file mode 100644 index aa2749b77..000000000 --- a/test/unit/fixtures/iframe.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - -

    visible

    -

    hidden

    - - diff --git a/test/unit/fixtures/logo.gif b/test/unit/fixtures/logo.gif deleted file mode 100644 index 71574abd7..000000000 Binary files a/test/unit/fixtures/logo.gif and /dev/null differ diff --git a/test/unit/phantomjs/core-extensions.js b/test/unit/phantomjs/core-extensions.js deleted file mode 100644 index 744ba99cd..000000000 --- a/test/unit/phantomjs/core-extensions.js +++ /dev/null @@ -1,70 +0,0 @@ -/*! - * PhantomJS Runners for Mocha - * https://github.com/metaskills/mocha-phantomjs/ - * - * Copyright (c) 2012 Ken Collins - * Released under the MIT license - * http://github.com/metaskills/mocha-phantomjs/blob/master/MIT-LICENSE - * - */ - -(function(){ - - // A shim for non ES5 supporting browsers, like PhantomJS. Lovingly inspired by: - // http://www.angrycoding.com/2011/09/to-bind-or-not-to-bind-that-is-in.html - if (!('bind' in Function.prototype)) { - Function.prototype.bind = function() { - var funcObj = this; - var extraArgs = Array.prototype.slice.call(arguments); - var thisObj = extraArgs.shift(); - return function() { - return funcObj.apply(thisObj, extraArgs.concat(Array.prototype.slice.call(arguments))); - }; - }; - } - - // Mocha needs a process.stdout.write in order to change the cursor position. - Mocha.process = Mocha.process || {}; - Mocha.process.stdout = Mocha.process.stdout || process.stdout; - Mocha.process.stdout.write = function(s) { window.callPhantom({"Mocha.process.stdout.write":s}); } - - // Mocha needs the formating feature of console.log so copy node's format function and - // monkey-patch it into place. This code is copied from node's, links copyright applies. - // https://github.com/joyent/node/blob/master/lib/util.js - console.format = function(f) { - if (typeof f !== 'string') { - var objects = []; - for (var i = 0; i < arguments.length; i++) { - objects.push(JSON.stringify(arguments[i])); - } - return objects.join(' '); - } - var i = 1; - var args = arguments; - var len = args.length; - var str = String(f).replace(/%[sdj%]/g, function(x) { - if (x === '%%') return '%'; - if (i >= len) return x; - switch (x) { - case '%s': return String(args[i++]); - case '%d': return Number(args[i++]); - case '%j': return JSON.stringify(args[i++]); - default: - return x; - } - }); - for (var x = args[i]; i < len; x = args[++i]) { - if (x === null || typeof x !== 'object') { - str += ' ' + x; - } else { - str += ' ' + JSON.stringify(x); - } - } - return str; - }; - var origError = console.error; - console.error = function(){ origError.call(console, console.format.apply(console, arguments)); }; - var origLog = console.log; - console.log = function(){ origLog.call(console, console.format.apply(console, arguments)); }; - -})(); diff --git a/test/unit/phantomjs/mocha-phantomjs.js b/test/unit/phantomjs/mocha-phantomjs.js deleted file mode 100644 index 51a9877d3..000000000 --- a/test/unit/phantomjs/mocha-phantomjs.js +++ /dev/null @@ -1,260 +0,0 @@ -/*! - * PhantomJS Runners for Mocha - * https://github.com/metaskills/mocha-phantomjs/ - * - * Copyright (c) 2012 Ken Collins - * Released under the MIT license - * http://github.com/metaskills/mocha-phantomjs/blob/master/MIT-LICENSE - * - */ - -// Generated by CoffeeScript 1.7.1 -(function() { - var Reporter, USAGE, config, mocha, reporter, system, webpage, - __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }; - - system = require('system'); - - webpage = require('webpage'); - - USAGE = "Usage: phantomjs mocha-phantomjs.coffee URL REPORTER [CONFIG]"; - - Reporter = (function() { - function Reporter(reporter, config) { - this.reporter = reporter; - this.config = config; - this.checkStarted = __bind(this.checkStarted, this); - this.waitForRunMocha = __bind(this.waitForRunMocha, this); - this.waitForInitMocha = __bind(this.waitForInitMocha, this); - this.waitForMocha = __bind(this.waitForMocha, this); - this.url = system.args[1]; - this.columns = parseInt(system.env.COLUMNS || 75) * .75 | 0; - this.mochaStarted = false; - this.mochaStartWait = this.config.timeout || 6000; - this.startTime = Date.now(); - if (!this.url) { - this.fail(USAGE); - } - } - - Reporter.prototype.run = function() { - this.initPage(); - return this.loadPage(); - }; - - Reporter.prototype.customizeMocha = function(options) { - return Mocha.reporters.Base.window.width = options.columns; - }; - - Reporter.prototype.customizeOptions = function() { - return { - columns: this.columns - }; - }; - - Reporter.prototype.fail = function(msg, errno) { - if (msg) { - console.log(msg); - } - return phantom.exit(errno || 1); - }; - - Reporter.prototype.finish = function() { - return phantom.exit(this.page.evaluate(function() { - return mochaPhantomJS.failures; - })); - }; - - Reporter.prototype.initPage = function() { - var cookie, _i, _len, _ref; - this.page = webpage.create({ - settings: this.config.settings - }); - if (this.config.headers) { - this.page.customHeaders = this.config.headers; - } - _ref = this.config.cookies || []; - for (_i = 0, _len = _ref.length; _i < _len; _i++) { - cookie = _ref[_i]; - this.page.addCookie(cookie); - } - if (this.config.viewportSize) { - this.page.viewportSize = this.config.viewportSize; - } - this.page.onConsoleMessage = function(msg) { - return system.stdout.writeLine(msg); - }; - this.page.onError = (function(_this) { - return function(msg, traces) { - var file, index, line, _j, _len1, _ref1; - if (_this.page.evaluate(function() { - return window.onerror != null; - })) { - return; - } - for (index = _j = 0, _len1 = traces.length; _j < _len1; index = ++_j) { - _ref1 = traces[index], line = _ref1.line, file = _ref1.file; - traces[index] = " " + file + ":" + line; - } - return _this.fail("" + msg + "\n\n" + (traces.join('\n'))); - }; - })(this); - return this.page.onInitialized = (function(_this) { - return function() { - return _this.page.evaluate(function(env) { - return window.mochaPhantomJS = { - env: env, - failures: 0, - ended: false, - started: false, - run: function() { - mochaPhantomJS.started = true; - return window.callPhantom({ - 'mochaPhantomJS.run': true - }); - } - }; - }, system.env); - }; - })(this); - }; - - Reporter.prototype.loadPage = function() { - this.page.open(this.url); - this.page.onLoadFinished = (function(_this) { - return function(status) { - _this.page.onLoadFinished = function() {}; - if (status !== 'success') { - _this.onLoadFailed(); - } - return _this.waitForInitMocha(); - }; - })(this); - return this.page.onCallback = (function(_this) { - return function(data) { - if (data.hasOwnProperty('Mocha.process.stdout.write')) { - system.stdout.write(data['Mocha.process.stdout.write']); - } else if (data.hasOwnProperty('mochaPhantomJS.run')) { - if (_this.injectJS()) { - _this.waitForRunMocha(); - } - } - return true; - }; - })(this); - }; - - Reporter.prototype.onLoadFailed = function() { - return this.fail("Failed to load the page. Check the url: " + this.url); - }; - - Reporter.prototype.injectJS = function() { - if (this.page.evaluate(function() { - return window.mocha != null; - })) { - this.page.injectJs('core-extensions.js'); - this.page.evaluate(this.customizeMocha, this.customizeOptions()); - return true; - } else { - this.fail("Failed to find mocha on the page."); - return false; - } - }; - - Reporter.prototype.runMocha = function() { - if (this.config.useColors === false) { - this.page.evaluate(function() { - return Mocha.reporters.Base.useColors = false; - }); - } - this.page.evaluate(this.runner, this.reporter); - this.mochaStarted = this.page.evaluate(function() { - return mochaPhantomJS.runner || false; - }); - if (this.mochaStarted) { - this.mochaRunAt = new Date().getTime(); - return this.waitForMocha(); - } else { - return this.fail("Failed to start mocha."); - } - }; - - Reporter.prototype.waitForMocha = function() { - var ended; - ended = this.page.evaluate(function() { - return mochaPhantomJS.ended; - }); - if (ended) { - return this.finish(); - } else { - return setTimeout(this.waitForMocha, 100); - } - }; - - Reporter.prototype.waitForInitMocha = function() { - if (!this.checkStarted()) { - return setTimeout(this.waitForInitMocha, 100); - } - }; - - Reporter.prototype.waitForRunMocha = function() { - if (this.checkStarted()) { - return this.runMocha(); - } else { - return setTimeout(this.waitForRunMocha, 100); - } - }; - - Reporter.prototype.checkStarted = function() { - var started; - started = this.page.evaluate(function() { - return mochaPhantomJS.started; - }); - if (!started && this.mochaStartWait && this.startTime + this.mochaStartWait < Date.now()) { - this.fail("Failed to start mocha: Init timeout", 255); - } - return started; - }; - - Reporter.prototype.runner = function(reporter) { - var cleanup, error, _ref, _ref1; - try { - mocha.setup({ - reporter: reporter - }); - mochaPhantomJS.runner = mocha.run(); - if (mochaPhantomJS.runner) { - cleanup = function() { - mochaPhantomJS.failures = mochaPhantomJS.runner.failures; - return mochaPhantomJS.ended = true; - }; - if ((_ref = mochaPhantomJS.runner) != null ? (_ref1 = _ref.stats) != null ? _ref1.end : void 0 : void 0) { - return cleanup(); - } else { - return mochaPhantomJS.runner.on('end', cleanup); - } - } - } catch (_error) { - error = _error; - return false; - } - }; - - return Reporter; - - })(); - - if (phantom.version.major !== 1 || phantom.version.minor < 9) { - console.log('mocha-phantomjs requires PhantomJS > 1.9.1'); - phantom.exit(-1); - } - - reporter = system.args[2] || 'spec'; - - config = JSON.parse(system.args[3] || '{}'); - - mocha = new Reporter(reporter, config); - - mocha.run(); - -}).call(this); diff --git a/test/unit/runner.rb b/test/unit/runner.rb deleted file mode 100644 index 26d3c7c37..000000000 --- a/test/unit/runner.rb +++ /dev/null @@ -1,402 +0,0 @@ -require 'pathname' -require 'sinatra/base' -require 'cgi' -require 'json' -require 'rbconfig' -require 'yaml' - -# A barebones runner for testing across multiple browsers quickly. -# -# Aims to be somewhat like the old unittest_js test runner, except that it's -# separate from the test server, and thus requires that the test server -# already be running. -# -# The fact that all unit tests can now run on one page means that we can -# simplify the test runner quite a bit. Here's what it does: -# -# 1. Based on the tests you told it to run (default: all tests), it generates -# a URL for running those tests on the test server. -# 2. It opens that URL in each of the browsers you specified (default: all -# browsers installed on your OS). -# 3. It spawns its own web server to listen for test results at a certain -# URL. The test server will hit that URL with the results (tests, passes, -# failures, duration) when the tests are done running. -# 4. It displays a summary of passes/failures in each browser. -# -# As with the old `rake test`, the `BROWSERS` and `TESTS` environment -# variables determine which browsers and tests you want to run. Multiple -# values should be comma-separated. -# -# Additionally, the test runner supports a `GREP` environment variable that -# will be passed along to Mocha. Give it a pattern (with standard regex -# syntax) and Mocha will run only the tests whose names match that pattern. -# -# USAGE -# ----- -# -# rake test:run -# # (will run all tests in all browsers) -# -# rake test:run BROWSERS=safari,firefox TESTS=string,number -# # (will run string and number tests in only Safari and Firefox) -# -# rake test:run BROWSERS=chrome GREP=gsub -# # (will run all tests whose names contain "gsub" in only Chrome) - -# TODO: -# -# - Figure out a better way to manage the Sinatra app. Forking is the best -# way to separate its stdout and stderr, but that doesn't work on Windows. -# - Allow the user to specify paths to browser executables via a YAML file or -# something. Especially crucial on Windows. -# - Get the test server to report more stuff about failures so that the -# runner's output can be more specific about what failed and why. -# - -module Runner - - host = RbConfig::CONFIG['host'] - IS_WINDOWS = host.include?('mswin') || host.include?('mingw32') - - class << self - PWD = Pathname.new(File.dirname(__FILE__)) - CONFIG_FILE = PWD.join('browsers.yml') - - unless CONFIG_FILE.exist? - # Copy the sample config file to an actual config file. - sample = PWD.join('browsers.sample.yml') - File.open(CONFIG_FILE, 'w') do |file| - file.write( File.read(sample) ) - end - end - - CONFIG = YAML::load_file(CONFIG_FILE) - - def config - CONFIG - end - end - - - module Browsers - - class Abstract - - def setup - end - - def teardown - end - - def supported? - true - end - - def host - RbConfig::CONFIG['host'] - end - - def macos? - host.include?('darwin') - end - - def windows? - host.include?('mswin') || host.include?('mingw32') - end - - def linux? - host.include?('linux') - end - - def configured_path - browsers = Runner::config['browsers'] - browsers[short_name.to_s] - end - - def default_path - nil - end - - def visit(url) - if windows? - system(%Q["#{path}" "#{url}"]) - elsif macos? - system("open -g -a '#{path}' '#{url}'") - elsif linux? - system(%Q["#{name}" "#{url}"]) - end - end - - def installed? - path && File.exists?(path) - end - - def name - n = self.class.name.split('::').last - linux? ? n.downcase : n - end - - def short_name - nil - end - - def escaped_name - name.gsub(' ', '\ ') - end - - def path - if macos? - File.expand_path("/Applications/#{name}.app") - else - configured_path || default_path || nil - end - end - end - - class Firefox < Abstract - - def short_name - :firefox - end - - def default_path - 'C:\Program Files\Mozilla Firefox\firefox.exe' - end - - def supported? - true - end - - end - - class IE < Abstract - - def short_name - :ie - end - - def setup - require 'win32ole' if windows? - end - - def supported? - windows? - end - - def installed? - windows? - end - - def visit(url) - ie = WIN32OLE.new('InternetExplorer.Application') - ie.visible = true - ie.Navigate(url) - end - - end - - class Safari < Abstract - - def short_name - :safari - end - - def supported? - macos? - end - - end - - class Chrome < Abstract - - def short_name - :chrome - end - - def default_path - 'C:\Program Files\Google\Chrome\Application\chrome.exe' - end - - def name - 'Google Chrome' - end - - end - - class Opera < Abstract - - def short_name - :opera - end - - def default_path - 'C:\Program Files\Opera\launcher.exe' - end - - end - - end # Browsers - - BROWSERS = { - :ie => Browsers::IE, - :firefox => Browsers::Firefox, - :chrome => Browsers::Chrome, - :safari => Browsers::Safari, - :opera => Browsers::Opera - } - - # A Sinatra app that listens for test results. Because we've separated the - # runner from the test server, it listens on a different port. The test - # page will make a JSONP call when all the tests have been run. - class ResultsListener < Sinatra::Base - set :port, 4568 - set :logging, false - - get '/results' do - results = { - "tests" => params[:tests].to_i, - "passes" => params[:passes].to_i, - "failures" => params[:failures].to_i, - "duration" => params[:duration].to_f - } - - if IS_WINDOWS - Runner::queue.push(results) - else - pipe = Runner::write_pipe - pipe.write(JSON.dump(results) + "\n") - end - - # We don't even need to render anything; the test page doesn't care - # about a response. - end - end - - class << self - - attr_accessor :read_pipe, :write_pipe - - def queue - @queue ||= Queue.new - end - - def run(browsers=nil, tests=nil, grep=nil) - @browsers = browsers.nil? ? BROWSERS.keys : - browsers.split(/\s*,\s*/).map(&:to_sym) - @tests = tests.nil? ? [] : tests.split(/\s*,\s*/).map(&:to_sym) - @grep = grep - - @browsers = @browsers.map { |b| get_browser(b).new } - - @url = %Q[http://127.0.0.1:4567/test/#{@tests.join(',')}?results_url=#{results_url}] - - if @grep && !@grep.nil? && !@grep.empty? - @url << "&grep=#{CGI::escape(@grep)}" - end - - # If we're on Linux/OS X, we want to fork off a process here, because - # it gives us better control over stdout/stderr. But Windows doesn't - # support forking, so we have to fall back to threads. - if IS_WINDOWS - thread_id = Thread.new do - # I don't see an easy way to turn off WEBrick's annoying logging, - # so let's just ignore it. - $stderr = StringIO.new - ResultsListener.run! - end - else - Runner::read_pipe, Runner::write_pipe = IO.pipe - - # Start up the Sinatra app to listen for test results, but do it in a - # fork because it sends some output to stdout and stderr that is - # irrelevant and annoying. - pid = fork do - Runner::read_pipe.close - STDOUT.reopen('/dev/null', 'w') - STDERR.reopen('/dev/null', 'w') - - ResultsListener.run! - end - - Runner::write_pipe.close - - # Make sure we clean up the forked process when we're done. - at_exit do - Process.kill(9, pid) - Process.wait(pid) - end - end - - trap('INT') { exit } - - results_table = {} - - @browsers.each do |browser| - if !browser.supported? - puts "Skipping #{browser.name} (not supported on this OS)" - next - end - if !browser.installed? - puts "Skipping #{browser.name} (not installed on this OS)" - puts " (edit test/unit/browsers.yml if this is in error)" - next - end - print "Running in #{browser.name}... " - - browser.setup - browser.visit(@url) - browser.teardown - - if IS_WINDOWS - # On Windows we need to slow down a bit. I don't know why. - sleep 2 - results = Runner::queue.pop - else - message = Runner::read_pipe.gets - results = JSON.parse(message) - end - puts "done." - results_table[browser.name] = results - end - - puts "\n\n" - - results_table.each do |k, v| - puts "Results for #{k}:" - report_results(v) - end - end - - def results_url - "http://127.0.0.1:4568/results" - end - - def get_browser(name) - BROWSERS[name] - end - - def report_results(results) - t, p, f, d = [ - results["tests"], - results["passes"], - results["failures"], - results["duration"] - ] - - summary = [ - "#{t} #{plural(t, 'test')}", - "#{p} #{plural(p, 'pass', 'passes')}", - "#{f} #{plural(f, 'failure')}" - ] - - puts %Q[#{summary.join(', ')} in #{d} #{plural(d, 'second')}\n] - end - - def plural(num, singular, plural=nil) - plural = "#{singular}s" if plural.nil? - num == 1 ? singular : plural - end - - end - -end \ No newline at end of file diff --git a/test/unit/server.rb b/test/unit/server.rb deleted file mode 100644 index 3e2c5bd3f..000000000 --- a/test/unit/server.rb +++ /dev/null @@ -1,174 +0,0 @@ -require 'sinatra/base' -require 'pathname' -require 'json' - -class UnitTests < Sinatra::Application - - PWD = Pathname.new( File.expand_path( File.dirname(__FILE__) ) ) - - UNIQUE_ASSET_STRING = Time.new.to_i - - set :root, PWD - set :public_folder, PWD.join('static') - - # Suppress logging. - set :logging, false - set :server_settings, { :AccessLog => [] } - - # By default, the server is only reachable locally. We change this so that - # we can start the server on one machine and then run tests from another. - set :bind, '0.0.0.0' - - PATH_TO_PROTOTYPE = PWD.join('..', '..', 'dist', 'prototype.js') - - unless PATH_TO_PROTOTYPE.file? - raise "You must run `rake dist` before starting the server." - end - - PATH_TO_TEST_JS = PWD.join('tests') - PATH_TO_FIXTURES = PWD.join('fixtures') - - SUITES = [] - - PATH_TO_TEST_JS.each_entry do |e| - next if e.directory? - basename = e.basename('.*').to_s - next if basename.start_with?('.') - SUITES << basename.sub('.test', '') - end - - SUITES_WITH_VIEWS = [] - - PWD.join('views', 'tests').each_entry do |e| - next if e.directory? - basename = e.basename('.*').to_s - SUITES_WITH_VIEWS << basename - end - - after do - headers({ - 'X-UA-Compatible' => 'IE=edge', - 'Cache-Control' => 'no-cache, no-store, must-revalidate', - 'Pragma' => 'no-cache', - 'Expires' => '0' - }) - end - - # The '/inspect' endpoint should be available regardless of HTTP method. - def self.handle_inspect(url, &block) - %w{get post put delete patch options head}.each do |verb| - self.send(verb, url, &block) - end - end - - def self.get_or_post(url, &block) - get(url, &block) - post(url, &block) - end - - get '/test' do - redirect to('/test/') - end - - get '/test/:names/' do - redirect to("/test/#{params[:names]}") - end - - # /test/ will run all tests; - # /test/foo,bar will run just "foo" and "bar" tests. - get '/test/:names?' do - names = params[:names] - @suites = names.nil? ? SUITES : names.split(/,/).uniq - @unique_asset_string = UNIQUE_ASSET_STRING.to_s - erb :tests, :locals => { :suites => @suites } - end - - # Will read from disk each time. No server restart necessary when the - # distributable is updated. - get '/prototype.js' do - content_type 'text/javascript' - send_file PATH_TO_PROTOTYPE - end - - - # We don't put either of these in the /static directory because - # (a) they should be more prominent in the directory structure; - # (b) they should never, ever get cached, and we want to enforce that - # aggressively. - get '/js/tests/:filename' do - filename = params[:filename] - path = PATH_TO_TEST_JS.join(filename) - if path.file? - content_type 'text/javascript' - send_file PATH_TO_TEST_JS.join(filename) - else - status 404 - end - end - - get '/fixtures/:filename' do - filename = params[:filename] - send_file PATH_TO_FIXTURES.join(filename) - end - - - # Routes for Ajax tests - - handle_inspect '/inspect' do - response = { - :headers => request_headers(request.env), - :method => request.request_method, - :body => request.body.read - } - - content_type 'application/json' - JSON.dump(response) - end - - get '/response' do - header_params = {} - params.each do |k, v| - v = v.gsub(/[\r\n]/, '') - header_params[k] = v - end - headers(header_params) - - if params[:'Content-Type'] - content_type params[:'Content-Type'].strip - else - content_type 'application/json' - end - - params[:responseBody] || "" - end - - # Collect all the headers that were sent with a request. (This is harder than - # it seems because of how Rack normalizes headers.) - def request_headers(env) - results = {} - - env.each do |k, v| - next unless k.start_with?('HTTP_') || k == 'CONTENT_TYPE' - key = k.sub('HTTP_', '').gsub('_', '-').downcase - results[key] = v - end - - results - end - - - not_found do - "File not found." - end - - - helpers do - - def suite_has_html?(suite) - SUITES_WITH_VIEWS.include?(suite) - end - - end - - # run! if app_file == $0 -end \ No newline at end of file diff --git a/test/unit/static/css/mocha.css b/test/unit/static/css/mocha.css deleted file mode 100644 index db0e388b9..000000000 --- a/test/unit/static/css/mocha.css +++ /dev/null @@ -1,259 +0,0 @@ -@charset "utf-8"; - -body { - margin:0; -} - -#mocha { - font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif; - margin: 60px 50px; -} - -#mocha ul, #mocha li { - margin: 0; - padding: 0; -} - -#mocha ul { - list-style: none; -} - -#mocha h1, #mocha h2 { - margin: 0; -} - -#mocha h1 { - margin-top: 15px; - font-size: 1em; - font-weight: 200; -} - -#mocha h1 a { - text-decoration: none; - color: inherit; -} - -#mocha h1 a:hover { - text-decoration: underline; -} - -#mocha .suite .suite h1 { - margin-top: 0; - font-size: .8em; -} - -#mocha .hidden { - display: none; -} - -#mocha h2 { - font-size: 12px; - font-weight: normal; - cursor: pointer; -} - -#mocha .suite { - margin-left: 15px; -} - -#mocha .test { - margin-left: 15px; - overflow: hidden; -} - -#mocha .test.pending:hover h2::after { - content: '(pending)'; - font-family: arial, sans-serif; -} - -#mocha .test.pass.medium .duration { - background: #C09853; -} - -#mocha .test.pass.slow .duration { - background: #B94A48; -} - -#mocha .test.pass::before { - content: '✓'; - font-size: 12px; - display: block; - float: left; - margin-right: 5px; - color: #00d6b2; -} - -#mocha .test.pass .duration { - font-size: 9px; - margin-left: 5px; - padding: 2px 5px; - color: white; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - box-shadow: inset 0 1px 1px rgba(0,0,0,.2); - -webkit-border-radius: 5px; - -moz-border-radius: 5px; - -ms-border-radius: 5px; - -o-border-radius: 5px; - border-radius: 5px; -} - -#mocha .test.pass.fast .duration { - display: none; -} - -#mocha .test.pending { - color: #0b97c4; -} - -#mocha .test.pending::before { - content: '◦'; - color: #0b97c4; -} - -#mocha .test.fail { - color: #c00; -} - -#mocha .test.fail pre { - color: black; -} - -#mocha .test.fail::before { - content: '✖'; - font-size: 12px; - display: block; - float: left; - margin-right: 5px; - color: #c00; -} - -#mocha .test pre.error { - color: #c00; - max-height: 300px; - overflow: auto; -} - -#mocha .test pre { - display: block; - float: left; - clear: left; - font: 12px/1.5 monaco, monospace; - margin: 5px; - padding: 15px; - border: 1px solid #eee; - border-bottom-color: #ddd; - -webkit-border-radius: 3px; - -webkit-box-shadow: 0 1px 3px #eee; - -moz-border-radius: 3px; - -moz-box-shadow: 0 1px 3px #eee; -} - -#mocha .test h2 { - position: relative; -} - -#mocha .test a.replay { - position: absolute; - top: 3px; - right: 0; - text-decoration: none; - vertical-align: middle; - display: block; - width: 15px; - height: 15px; - line-height: 15px; - text-align: center; - background: #eee; - font-size: 15px; - -moz-border-radius: 15px; - border-radius: 15px; - -webkit-transition: opacity 200ms; - -moz-transition: opacity 200ms; - transition: opacity 200ms; - opacity: 0.3; - color: #888; -} - -#mocha .test:hover a.replay { - opacity: 1; -} - -#mocha-report.pass .test.fail { - display: none; -} - -#mocha-report.fail .test.pass { - display: none; -} - -#mocha-report.pending .test.pass -#mocha-report.pending .test.fail, { - display: none; -} -#mocha-report.pending .test.pass.pending { - display: block; -} - -#mocha-error { - color: #c00; - font-size: 1.5em; - font-weight: 100; - letter-spacing: 1px; -} - -#mocha-stats { - position: fixed; - top: 15px; - right: 10px; - font-size: 12px; - margin: 0; - color: #888; - z-index: 1; -} - -#mocha-stats .progress { - float: right; - padding-top: 0; -} - -#mocha-stats em { - color: black; -} - -#mocha-stats a { - text-decoration: none; - color: inherit; -} - -#mocha-stats a:hover { - border-bottom: 1px solid #eee; -} - -#mocha-stats li { - display: inline-block; - margin: 0 5px; - list-style: none; - padding-top: 11px; -} - -#mocha-stats canvas { - width: 40px; - height: 40px; -} - -#mocha code .comment { color: #ddd } -#mocha code .init { color: #2F6FAD } -#mocha code .string { color: #5890AD } -#mocha code .keyword { color: #8A6343 } -#mocha code .number { color: #2F6FAD } - -@media screen and (max-device-width: 480px) { - #mocha { - margin: 60px 0px; - } - - #mocha #stats { - position: absolute; - } -} \ No newline at end of file diff --git a/test/unit/static/js/assertions.js b/test/unit/static/js/assertions.js deleted file mode 100644 index a56b5e4a5..000000000 --- a/test/unit/static/js/assertions.js +++ /dev/null @@ -1,472 +0,0 @@ - -(function () { - - function ok(val, message) { - if (!!!val) { - fail(val, true, message, '=='); - } - } - - function buildMessage() { - var args = $A(arguments), template = args.shift(); - return template.interpolate(args); - } - - function fail (actual, expected, message, operator, stackStartFunction) { - throw new AssertionError({ - message: message, - actual: actual, - expected: expected, - operator: operator, - stackStartFunction: stackStartFunction - }); - } - - // Utility for deep equality testing of objects - function objectsEqual (obj1, obj2) { - /* jshint eqeqeq: false */ - - // Check for undefined or null - if (isUndefinedOrNull(obj1) || isUndefinedOrNull(obj2)) { - return false; - } - - // Object prototypes must be the same - if (obj1.prototype !== obj2.prototype) { - return false; - } - - // Handle argument objects - if (isArgumentsObject(obj1)) { - if (!isArgumentsObject(obj2)) { - return false; - } - obj1 = Array.prototype.slice.call(obj1); - obj2 = Array.prototype.slice.call(obj2); - } - - // Check number of own properties - var obj1Keys = getObjectKeys(obj1); - var obj2Keys = getObjectKeys(obj2); - if (obj1Keys.length !== obj2Keys.length) { - return false; - } - - obj1Keys.sort(); - obj2Keys.sort(); - - // Cheap initial key test (see https://github.com/joyent/node/blob/master/lib/assert.js) - var key, i, len = obj1Keys.length; - for (i = 0; i < len; i += 1) { - if (obj1Keys[i] != obj2Keys[i]) { - return false; - } - } - - // Expensive deep test - for (i = 0; i < len; i += 1) { - key = obj1Keys[i]; - if (!isDeepEqual(obj1[key], obj2[key])) { - return false; - } - } - - // If it got this far... - return true; - } - - // Utility for deep equality testing - function isDeepEqual (actual, expected) { - /* jshint eqeqeq: false */ - if (actual === expected) { - return true; - } - if (expected instanceof Date && actual instanceof Date) { - return actual.getTime() === expected.getTime(); - } - if (actual instanceof RegExp && expected instanceof RegExp) { - return ( - actual.source === expected.source && - actual.global === expected.global && - actual.multiline === expected.multiline && - actual.lastIndex === expected.lastIndex && - actual.ignoreCase === expected.ignoreCase - ); - } - if (typeof actual !== 'object' && typeof expected !== 'object') { - return actual == expected; - } - return objectsEqual(actual, expected); - } - - // Utility for testing whether a function throws an error - function functionThrows (fn, expected) { - - // Try/catch - var thrown = false; - var thrownError; - try { - fn(); - } catch (err) { - thrown = true; - thrownError = err; - } - - // Check error - if (thrown && expected) { - thrown = errorMatches(thrownError, expected); - } - - return thrown; - } - - // Utility for checking whether an error matches a given constructor, regexp or string - function errorMatches (actual, expected) { - if (typeof expected === 'string') { - return actual.message === expected; - } - if (expected instanceof RegExp) { - return expected.test(actual.message); - } - if (actual instanceof expected) { - return true; - } - return false; - } - - function AssertionError (opts) { - opts = opts || {}; - - this.name = 'AssertionError'; - this.actual = opts.actual; - this.expected = opts.expected; - this.operator = opts.operator || ''; - this.message = opts.message; - - if (!this.message) { - this.message = this.toString(); - } - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, opts.stackStartFunction || fail); - } - } - - AssertionError.prototype = (Object.create ? Object.create(Error.prototype) : new Error()); - AssertionError.prototype.name = 'AssertionError'; - AssertionError.prototype.constructor = AssertionError; - - // Assertion error to string - AssertionError.prototype.toString = function () { - if (this.message) { - return this.name + ': ' +this.message; - } else { - return this.name + ': ' + - this.actual + ' ' + - this.operator + ' ' + - this.expected; - } - }; - - - var assert = ok; - - Object.extend(assert, { - - equal: function (actual, expected, message) { - if (actual != expected) { - var msg = buildMessage(message, 'expected "#{0}" to equal "#{1}"', - actual, expected); - fail(actual, expected, msg, '=='); - } - }, - - notEqual: function (actual, expected, message) { - if (actual == expected) { - var msg = buildMessage(message, 'expected "#{0}" not to equal "#{1}"', - actual, expected); - fail(actual, expected, msg, '!='); - } - }, - - strictEqual: function (actual, expected, message) { - if (actual !== expected) { - var msg = buildMessage( - message, - 'expected "#{0}" to strictly equal "#{1}"', - actual, - expected - ); - fail(actual, expected, msg, '==='); - } - }, - - notStrictEqual: function (actual, expected, message) { - if (actual === expected) { - var msg = buildMessage( - message, - 'expected "#{0}" not to strictly equal "#{1}"', - actual, - expected - ); - fail(actual, expected, msg, '!='); - } - }, - - deepEqual: function (actual, expected, message) { - if (!isDeepEqual(actual, expected)) { - var msg = buildMessage( - message, - 'expected #{0} to deep-equal #{1}', - actual, - expected - ); - fail(actual, expected, msg, 'deepEqual'); - } - }, - - notDeepEqual: function (actual, expected, message) { - if (isDeepEqual(actual, expected)) { - var msg = buildMessage( - message, - 'expected #{0} not to deep-equal #{1}', - actual, - expected - ); - fail(actual, expected, msg, 'notDeepEqual'); - } - }, - - 'throws': function (fn, expected, message) { - if (!functionThrows(fn, expected)) { - var msg = buildMessage( - message, - 'expected function to throw #{0}', - expected || 'error' - ); - fail(val, true, msg, 'throws'); - } - }, - - doesNotThrow: function (fn, expected, message) { - if (functionThrows(fn, expected)) { - var msg = buildMessage( - message, - 'expected function not to throw #{0}', - expected || 'error' - ); - } - }, - - isTypeOf: function (val, type, message) { - if (typeof val !== type) { - var msg = buildMessage( - message, - 'expected "#{0}" to be of type #{1}', - val, type - ); - fail(val, type, msg, 'isTypeOf'); - } - }, - - isNotTypeOf: function (val, type, message) { - if (typeof val === type) { - var msg = buildMessage( - message, - 'expected "#{0}" not to be of type #{1}', - val, type - ); - fail(val, type, msg, 'isNotTypeOf'); - } - }, - - isInstanceOf: function (val, constructor, message) { - if (!(val instanceof constructor)) { - var msg = buildMessage( - message, - 'expected #{0} to be an instance of #{1}', - val, constructor - ); - fail(val, constructor, msg, 'instanceof'); - } - }, - - isNotInstanceOf: function (val, constructor, message) { - if (val instanceof constructor) { - var msg = buildMessage( - message, - 'expected #{0} not to be an instance of #{1}', - val, constructor - ); - fail(val, constructor, msg, '!instanceof'); - } - }, - - isNull: function (val, message) { - if (val !== null) { - var msg = buildMessage( - message, - 'expected #{0} to be null', - val - ); - fail(val, null, msg, 'isNull'); - } - }, - - isNotNull: function (val, message) { - if (val === null) { - var msg = buildMessage( - message, - 'expected #{0} not to be null', - val - ); - fail(val, null, msg, 'isNotNull'); - } - }, - - isUndefined: function (val, message) { - var undef; - if (typeof val !== 'undefined') { - var msg = buildMessage( - message, - 'expected #{0} to be undefined', - val - ); - fail(val, undef, msg, 'isUndefined'); - } - }, - - isDefined: function (val, message) { - var undef; - if (typeof val === 'undefined') { - var msg = buildMessage( - message, - 'expected #{0} to be defined', - val - ); - fail(val, undef, msg, 'isDefined'); - } - }, - - match: function (actual, expected, message) { - if (!expected.test(actual)) { - var msg = buildMessage( - message, - 'expected #{0} to match #{1}', - actual, - expected - ); - fail(actual, expected, msg, 'match'); - } - }, - - notMatch: function (actual, expected, message) { - if (expected.test(actual)) { - var msg = buildMessage( - message, - 'expected #{0} not to match #{1}', - actual, - expected - ); - fail(actual, expected, msg, '!match'); - } - }, - - enumEqual: function (expected, actual, message) { - expected = $A(expected); - actual = $A(actual); - - var passes = expected.length == actual.length && - expected.zip(actual).all(function(pair) { return pair[0] == pair[1]; }); - - if (!passes) { - var msg = buildMessage( - message, - 'expected collection #{0} to match collection #{1}', - actual, - expected - ); - fail(actual, expected, msg, 'enumEqual'); - } - }, - - enabled: function () { - for (var i = 0, element; element = arguments[i]; i++) { - assert( - !$(element).disabled, - 'element was disabled: ' + Object.inspect(element) - ); - } - }, - - disabled: function () { - for (var i = 0, element; element = arguments[i]; i++) { - assert( - $(element).disabled, - 'element was enabled: ' + Object.inspect(element) - ); - } - }, - - respondsTo: function (method, obj, message) { - var passes = (method in obj) && (typeof obj[method] === 'function'); - - if (!passes) { - var msg = buildMessage( - message || 'assert.respondsTo', - 'expected #{0} to respond to method "#{1}"', - obj, - method - ); - fail(obj, method, msg, 'respondsTo'); - } - }, - - elementsMatch: function () { - var message, passes = true, expressions = $A(arguments), elements = $A(expressions.shift()); - - if (elements.length !== expressions.length) { - passes = false; - message = 'Size mismatch: #{0} elements, #{1} expressions (#{2})'.interpolate( - [elements.length, expressions.length, expressions]); - } else { - elements.zip(expressions).all(function (pair, index) { - var element = $(pair.first()), expression = pair.last(); - if (element.match(expression)) return true; - - message = 'in index <#{0}>: expected <#{1}> but got #{2}'.interpolate( - [index, expression, Object.inspect(element)]); - passes = false; - }); - } - - assert(passes, message); - }, - - elementMatches: function (element, expression, message) { - assert.elementsMatch([element], expression); - } - - }); - - - - // Exports - // ------- - - // AMD - if (typeof define !== 'undefined' && define.amd) { - define([], function () { - return assert; - }); - } - // CommonJS - else if (typeof module !== 'undefined' && module.exports) { - module.exports = assert; - } - // Script tag - else { - root.assert = assert; - } - -})(this); \ No newline at end of file diff --git a/test/unit/static/js/mocha.js b/test/unit/static/js/mocha.js deleted file mode 100644 index 41f89a7d6..000000000 --- a/test/unit/static/js/mocha.js +++ /dev/null @@ -1,5441 +0,0 @@ -;(function(){ - -// CommonJS require() - -function require(p){ - var path = require.resolve(p) - , mod = require.modules[path]; - if (!mod) throw new Error('failed to require "' + p + '"'); - if (!mod.exports) { - mod.exports = {}; - mod.call(mod.exports, mod, mod.exports, require.relative(path)); - } - return mod.exports; - } - -require.modules = {}; - -require.resolve = function (path){ - var orig = path - , reg = path + '.js' - , index = path + '/index.js'; - return require.modules[reg] && reg - || require.modules[index] && index - || orig; - }; - -require.register = function (path, fn){ - require.modules[path] = fn; - }; - -require.relative = function (parent) { - return function(p){ - if ('.' != p.charAt(0)) return require(p); - - var path = parent.split('/') - , segs = p.split('/'); - path.pop(); - - for (var i = 0; i < segs.length; i++) { - var seg = segs[i]; - if ('..' == seg) path.pop(); - else if ('.' != seg) path.push(seg); - } - - return require(path.join('/')); - }; - }; - - -require.register("browser/debug.js", function(module, exports, require){ - -module.exports = function(type){ - return function(){ - } -}; - -}); // module: browser/debug.js - -require.register("browser/diff.js", function(module, exports, require){ -/* See license.txt for terms of usage */ - -/* - * Text diff implementation. - * - * This library supports the following APIS: - * JsDiff.diffChars: Character by character diff - * JsDiff.diffWords: Word (as defined by \b regex) diff which ignores whitespace - * JsDiff.diffLines: Line based diff - * - * JsDiff.diffCss: Diff targeted at CSS content - * - * These methods are based on the implementation proposed in - * "An O(ND) Difference Algorithm and its Variations" (Myers, 1986). - * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.4.6927 - */ -var JsDiff = (function() { - function clonePath(path) { - return { newPos: path.newPos, components: path.components.slice(0) }; - } - function removeEmpty(array) { - var ret = []; - for (var i = 0; i < array.length; i++) { - if (array[i]) { - ret.push(array[i]); - } - } - return ret; - } - function escapeHTML(s) { - var n = s; - n = n.replace(/&/g, "&"); - n = n.replace(//g, ">"); - n = n.replace(/"/g, """); - - return n; - } - - - var fbDiff = function(ignoreWhitespace) { - this.ignoreWhitespace = ignoreWhitespace; - }; - fbDiff.prototype = { - diff: function(oldString, newString) { - // Handle the identity case (this is due to unrolling editLength == 0 - if (newString == oldString) { - return [{ value: newString }]; - } - if (!newString) { - return [{ value: oldString, removed: true }]; - } - if (!oldString) { - return [{ value: newString, added: true }]; - } - - newString = this.tokenize(newString); - oldString = this.tokenize(oldString); - - var newLen = newString.length, oldLen = oldString.length; - var maxEditLength = newLen + oldLen; - var bestPath = [{ newPos: -1, components: [] }]; - - // Seed editLength = 0 - var oldPos = this.extractCommon(bestPath[0], newString, oldString, 0); - if (bestPath[0].newPos+1 >= newLen && oldPos+1 >= oldLen) { - return bestPath[0].components; - } - - for (var editLength = 1; editLength <= maxEditLength; editLength++) { - for (var diagonalPath = -1*editLength; diagonalPath <= editLength; diagonalPath+=2) { - var basePath; - var addPath = bestPath[diagonalPath-1], - removePath = bestPath[diagonalPath+1]; - oldPos = (removePath ? removePath.newPos : 0) - diagonalPath; - if (addPath) { - // No one else is going to attempt to use this value, clear it - bestPath[diagonalPath-1] = undefined; - } - - var canAdd = addPath && addPath.newPos+1 < newLen; - var canRemove = removePath && 0 <= oldPos && oldPos < oldLen; - if (!canAdd && !canRemove) { - bestPath[diagonalPath] = undefined; - continue; - } - - // Select the diagonal that we want to branch from. We select the prior - // path whose position in the new string is the farthest from the origin - // and does not pass the bounds of the diff graph - if (!canAdd || (canRemove && addPath.newPos < removePath.newPos)) { - basePath = clonePath(removePath); - this.pushComponent(basePath.components, oldString[oldPos], undefined, true); - } else { - basePath = clonePath(addPath); - basePath.newPos++; - this.pushComponent(basePath.components, newString[basePath.newPos], true, undefined); - } - - var oldPos = this.extractCommon(basePath, newString, oldString, diagonalPath); - - if (basePath.newPos+1 >= newLen && oldPos+1 >= oldLen) { - return basePath.components; - } else { - bestPath[diagonalPath] = basePath; - } - } - } - }, - - pushComponent: function(components, value, added, removed) { - var last = components[components.length-1]; - if (last && last.added === added && last.removed === removed) { - // We need to clone here as the component clone operation is just - // as shallow array clone - components[components.length-1] = - {value: this.join(last.value, value), added: added, removed: removed }; - } else { - components.push({value: value, added: added, removed: removed }); - } - }, - extractCommon: function(basePath, newString, oldString, diagonalPath) { - var newLen = newString.length, - oldLen = oldString.length, - newPos = basePath.newPos, - oldPos = newPos - diagonalPath; - while (newPos+1 < newLen && oldPos+1 < oldLen && this.equals(newString[newPos+1], oldString[oldPos+1])) { - newPos++; - oldPos++; - - this.pushComponent(basePath.components, newString[newPos], undefined, undefined); - } - basePath.newPos = newPos; - return oldPos; - }, - - equals: function(left, right) { - var reWhitespace = /\S/; - if (this.ignoreWhitespace && !reWhitespace.test(left) && !reWhitespace.test(right)) { - return true; - } else { - return left == right; - } - }, - join: function(left, right) { - return left + right; - }, - tokenize: function(value) { - return value; - } - }; - - var CharDiff = new fbDiff(); - - var WordDiff = new fbDiff(true); - WordDiff.tokenize = function(value) { - return removeEmpty(value.split(/(\s+|\b)/)); - }; - - var CssDiff = new fbDiff(true); - CssDiff.tokenize = function(value) { - return removeEmpty(value.split(/([{}:;,]|\s+)/)); - }; - - var LineDiff = new fbDiff(); - LineDiff.tokenize = function(value) { - return value.split(/^/m); - }; - - return { - diffChars: function(oldStr, newStr) { return CharDiff.diff(oldStr, newStr); }, - diffWords: function(oldStr, newStr) { return WordDiff.diff(oldStr, newStr); }, - diffLines: function(oldStr, newStr) { return LineDiff.diff(oldStr, newStr); }, - - diffCss: function(oldStr, newStr) { return CssDiff.diff(oldStr, newStr); }, - - createPatch: function(fileName, oldStr, newStr, oldHeader, newHeader) { - var ret = []; - - ret.push("Index: " + fileName); - ret.push("==================================================================="); - ret.push("--- " + fileName + (typeof oldHeader === "undefined" ? "" : "\t" + oldHeader)); - ret.push("+++ " + fileName + (typeof newHeader === "undefined" ? "" : "\t" + newHeader)); - - var diff = LineDiff.diff(oldStr, newStr); - if (!diff[diff.length-1].value) { - diff.pop(); // Remove trailing newline add - } - diff.push({value: "", lines: []}); // Append an empty value to make cleanup easier - - function contextLines(lines) { - return lines.map(function(entry) { return ' ' + entry; }); - } - function eofNL(curRange, i, current) { - var last = diff[diff.length-2], - isLast = i === diff.length-2, - isLastOfType = i === diff.length-3 && (current.added === !last.added || current.removed === !last.removed); - - // Figure out if this is the last line for the given file and missing NL - if (!/\n$/.test(current.value) && (isLast || isLastOfType)) { - curRange.push('\\ No newline at end of file'); - } - } - - var oldRangeStart = 0, newRangeStart = 0, curRange = [], - oldLine = 1, newLine = 1; - for (var i = 0; i < diff.length; i++) { - var current = diff[i], - lines = current.lines || current.value.replace(/\n$/, "").split("\n"); - current.lines = lines; - - if (current.added || current.removed) { - if (!oldRangeStart) { - var prev = diff[i-1]; - oldRangeStart = oldLine; - newRangeStart = newLine; - - if (prev) { - curRange = contextLines(prev.lines.slice(-4)); - oldRangeStart -= curRange.length; - newRangeStart -= curRange.length; - } - } - curRange.push.apply(curRange, lines.map(function(entry) { return (current.added?"+":"-") + entry; })); - eofNL(curRange, i, current); - - if (current.added) { - newLine += lines.length; - } else { - oldLine += lines.length; - } - } else { - if (oldRangeStart) { - // Close out any changes that have been output (or join overlapping) - if (lines.length <= 8 && i < diff.length-2) { - // Overlapping - curRange.push.apply(curRange, contextLines(lines)); - } else { - // end the range and output - var contextSize = Math.min(lines.length, 4); - ret.push( - "@@ -" + oldRangeStart + "," + (oldLine-oldRangeStart+contextSize) - + " +" + newRangeStart + "," + (newLine-newRangeStart+contextSize) - + " @@"); - ret.push.apply(ret, curRange); - ret.push.apply(ret, contextLines(lines.slice(0, contextSize))); - if (lines.length <= 4) { - eofNL(ret, i, current); - } - - oldRangeStart = 0; newRangeStart = 0; curRange = []; - } - } - oldLine += lines.length; - newLine += lines.length; - } - } - - return ret.join('\n') + '\n'; - }, - - convertChangesToXML: function(changes){ - var ret = []; - for ( var i = 0; i < changes.length; i++) { - var change = changes[i]; - if (change.added) { - ret.push(""); - } else if (change.removed) { - ret.push(""); - } - - ret.push(escapeHTML(change.value)); - - if (change.added) { - ret.push(""); - } else if (change.removed) { - ret.push(""); - } - } - return ret.join(""); - } - }; -})(); - -if (typeof module !== "undefined") { - module.exports = JsDiff; -} - -}); // module: browser/diff.js - -require.register("browser/events.js", function(module, exports, require){ - -/** - * Module exports. - */ - -exports.EventEmitter = EventEmitter; - -/** - * Check if `obj` is an array. - */ - -function isArray(obj) { - return '[object Array]' == {}.toString.call(obj); -} - -/** - * Event emitter constructor. - * - * @api public - */ - -function EventEmitter(){}; - -/** - * Adds a listener. - * - * @api public - */ - -EventEmitter.prototype.on = function (name, fn) { - if (!this.$events) { - this.$events = {}; - } - - if (!this.$events[name]) { - this.$events[name] = fn; - } else if (isArray(this.$events[name])) { - this.$events[name].push(fn); - } else { - this.$events[name] = [this.$events[name], fn]; - } - - return this; -}; - -EventEmitter.prototype.addListener = EventEmitter.prototype.on; - -/** - * Adds a volatile listener. - * - * @api public - */ - -EventEmitter.prototype.once = function (name, fn) { - var self = this; - - function on () { - self.removeListener(name, on); - fn.apply(this, arguments); - }; - - on.listener = fn; - this.on(name, on); - - return this; -}; - -/** - * Removes a listener. - * - * @api public - */ - -EventEmitter.prototype.removeListener = function (name, fn) { - if (this.$events && this.$events[name]) { - var list = this.$events[name]; - - if (isArray(list)) { - var pos = -1; - - for (var i = 0, l = list.length; i < l; i++) { - if (list[i] === fn || (list[i].listener && list[i].listener === fn)) { - pos = i; - break; - } - } - - if (pos < 0) { - return this; - } - - list.splice(pos, 1); - - if (!list.length) { - delete this.$events[name]; - } - } else if (list === fn || (list.listener && list.listener === fn)) { - delete this.$events[name]; - } - } - - return this; -}; - -/** - * Removes all listeners for an event. - * - * @api public - */ - -EventEmitter.prototype.removeAllListeners = function (name) { - if (name === undefined) { - this.$events = {}; - return this; - } - - if (this.$events && this.$events[name]) { - this.$events[name] = null; - } - - return this; -}; - -/** - * Gets all listeners for a certain event. - * - * @api public - */ - -EventEmitter.prototype.listeners = function (name) { - if (!this.$events) { - this.$events = {}; - } - - if (!this.$events[name]) { - this.$events[name] = []; - } - - if (!isArray(this.$events[name])) { - this.$events[name] = [this.$events[name]]; - } - - return this.$events[name]; -}; - -/** - * Emits an event. - * - * @api public - */ - -EventEmitter.prototype.emit = function (name) { - if (!this.$events) { - return false; - } - - var handler = this.$events[name]; - - if (!handler) { - return false; - } - - var args = [].slice.call(arguments, 1); - - if ('function' == typeof handler) { - handler.apply(this, args); - } else if (isArray(handler)) { - var listeners = handler.slice(); - - for (var i = 0, l = listeners.length; i < l; i++) { - listeners[i].apply(this, args); - } - } else { - return false; - } - - return true; -}; -}); // module: browser/events.js - -require.register("browser/fs.js", function(module, exports, require){ - -}); // module: browser/fs.js - -require.register("browser/path.js", function(module, exports, require){ - -}); // module: browser/path.js - -require.register("browser/progress.js", function(module, exports, require){ - -/** - * Expose `Progress`. - */ - -module.exports = Progress; - -/** - * Initialize a new `Progress` indicator. - */ - -function Progress() { - this.percent = 0; - this.size(0); - this.fontSize(11); - this.font('helvetica, arial, sans-serif'); -} - -/** - * Set progress size to `n`. - * - * @param {Number} n - * @return {Progress} for chaining - * @api public - */ - -Progress.prototype.size = function(n){ - this._size = n; - return this; -}; - -/** - * Set text to `str`. - * - * @param {String} str - * @return {Progress} for chaining - * @api public - */ - -Progress.prototype.text = function(str){ - this._text = str; - return this; -}; - -/** - * Set font size to `n`. - * - * @param {Number} n - * @return {Progress} for chaining - * @api public - */ - -Progress.prototype.fontSize = function(n){ - this._fontSize = n; - return this; -}; - -/** - * Set font `family`. - * - * @param {String} family - * @return {Progress} for chaining - */ - -Progress.prototype.font = function(family){ - this._font = family; - return this; -}; - -/** - * Update percentage to `n`. - * - * @param {Number} n - * @return {Progress} for chaining - */ - -Progress.prototype.update = function(n){ - this.percent = n; - return this; -}; - -/** - * Draw on `ctx`. - * - * @param {CanvasRenderingContext2d} ctx - * @return {Progress} for chaining - */ - -Progress.prototype.draw = function(ctx){ - var percent = Math.min(this.percent, 100) - , size = this._size - , half = size / 2 - , x = half - , y = half - , rad = half - 1 - , fontSize = this._fontSize; - - ctx.font = fontSize + 'px ' + this._font; - - var angle = Math.PI * 2 * (percent / 100); - ctx.clearRect(0, 0, size, size); - - // outer circle - ctx.strokeStyle = '#9f9f9f'; - ctx.beginPath(); - ctx.arc(x, y, rad, 0, angle, false); - ctx.stroke(); - - // inner circle - ctx.strokeStyle = '#eee'; - ctx.beginPath(); - ctx.arc(x, y, rad - 1, 0, angle, true); - ctx.stroke(); - - // text - var text = this._text || (percent | 0) + '%' - , w = ctx.measureText(text).width; - - ctx.fillText( - text - , x - w / 2 + 1 - , y + fontSize / 2 - 1); - - return this; -}; - -}); // module: browser/progress.js - -require.register("browser/tty.js", function(module, exports, require){ - -exports.isatty = function(){ - return true; -}; - -exports.getWindowSize = function(){ - if ('innerHeight' in global) { - return [global.innerHeight, global.innerWidth]; - } else { - // In a Web Worker, the DOM Window is not available. - return [640, 480]; - } -}; - -}); // module: browser/tty.js - -require.register("context.js", function(module, exports, require){ - -/** - * Expose `Context`. - */ - -module.exports = Context; - -/** - * Initialize a new `Context`. - * - * @api private - */ - -function Context(){} - -/** - * Set or get the context `Runnable` to `runnable`. - * - * @param {Runnable} runnable - * @return {Context} - * @api private - */ - -Context.prototype.runnable = function(runnable){ - if (0 == arguments.length) return this._runnable; - this.test = this._runnable = runnable; - return this; -}; - -/** - * Set test timeout `ms`. - * - * @param {Number} ms - * @return {Context} self - * @api private - */ - -Context.prototype.timeout = function(ms){ - this.runnable().timeout(ms); - return this; -}; - -/** - * Set test slowness threshold `ms`. - * - * @param {Number} ms - * @return {Context} self - * @api private - */ - -Context.prototype.slow = function(ms){ - this.runnable().slow(ms); - return this; -}; - -/** - * Inspect the context void of `._runnable`. - * - * @return {String} - * @api private - */ - -Context.prototype.inspect = function(){ - return JSON.stringify(this, function(key, val){ - if ('_runnable' == key) return; - if ('test' == key) return; - return val; - }, 2); -}; - -}); // module: context.js - -require.register("hook.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Runnable = require('./runnable'); - -/** - * Expose `Hook`. - */ - -module.exports = Hook; - -/** - * Initialize a new `Hook` with the given `title` and callback `fn`. - * - * @param {String} title - * @param {Function} fn - * @api private - */ - -function Hook(title, fn) { - Runnable.call(this, title, fn); - this.type = 'hook'; -} - -/** - * Inherit from `Runnable.prototype`. - */ - -function F(){}; -F.prototype = Runnable.prototype; -Hook.prototype = new F; -Hook.prototype.constructor = Hook; - - -/** - * Get or set the test `err`. - * - * @param {Error} err - * @return {Error} - * @api public - */ - -Hook.prototype.error = function(err){ - if (0 == arguments.length) { - var err = this._error; - this._error = null; - return err; - } - - this._error = err; -}; - -}); // module: hook.js - -require.register("interfaces/bdd.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Suite = require('../suite') - , Test = require('../test'); - -/** - * BDD-style interface: - * - * describe('Array', function(){ - * describe('#indexOf()', function(){ - * it('should return -1 when not present', function(){ - * - * }); - * - * it('should return the index when present', function(){ - * - * }); - * }); - * }); - * - */ - -module.exports = function(suite){ - var suites = [suite]; - - suite.on('pre-require', function(context, file, mocha){ - - /** - * Execute before running tests. - */ - - context.before = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after running tests. - */ - - context.after = function(fn){ - suites[0].afterAll(fn); - }; - - /** - * Execute before each test case. - */ - - context.beforeEach = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.afterEach = function(fn){ - suites[0].afterEach(fn); - }; - - /** - * Describe a "suite" with the given `title` - * and callback `fn` containing nested suites - * and/or tests. - */ - - context.describe = context.context = function(title, fn){ - var suite = Suite.create(suites[0], title); - suites.unshift(suite); - fn.call(suite); - suites.shift(); - return suite; - }; - - /** - * Pending describe. - */ - - context.xdescribe = - context.xcontext = - context.describe.skip = function(title, fn){ - var suite = Suite.create(suites[0], title); - suite.pending = true; - suites.unshift(suite); - fn.call(suite); - suites.shift(); - }; - - /** - * Exclusive suite. - */ - - context.describe.only = function(title, fn){ - var suite = context.describe(title, fn); - mocha.grep(suite.fullTitle()); - }; - - /** - * Describe a specification or test-case - * with the given `title` and callback `fn` - * acting as a thunk. - */ - - context.it = context.specify = function(title, fn){ - var suite = suites[0]; - if (suite.pending) var fn = null; - var test = new Test(title, fn); - suite.addTest(test); - return test; - }; - - /** - * Exclusive test-case. - */ - - context.it.only = function(title, fn){ - var test = context.it(title, fn); - mocha.grep(test.fullTitle()); - }; - - /** - * Pending test case. - */ - - context.xit = - context.xspecify = - context.it.skip = function(title){ - context.it(title); - }; - }); -}; - -}); // module: interfaces/bdd.js - -require.register("interfaces/exports.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Suite = require('../suite') - , Test = require('../test'); - -/** - * TDD-style interface: - * - * exports.Array = { - * '#indexOf()': { - * 'should return -1 when the value is not present': function(){ - * - * }, - * - * 'should return the correct index when the value is present': function(){ - * - * } - * } - * }; - * - */ - -module.exports = function(suite){ - var suites = [suite]; - - suite.on('require', visit); - - function visit(obj) { - var suite; - for (var key in obj) { - if ('function' == typeof obj[key]) { - var fn = obj[key]; - switch (key) { - case 'before': - suites[0].beforeAll(fn); - break; - case 'after': - suites[0].afterAll(fn); - break; - case 'beforeEach': - suites[0].beforeEach(fn); - break; - case 'afterEach': - suites[0].afterEach(fn); - break; - default: - suites[0].addTest(new Test(key, fn)); - } - } else { - var suite = Suite.create(suites[0], key); - suites.unshift(suite); - visit(obj[key]); - suites.shift(); - } - } - } -}; - -}); // module: interfaces/exports.js - -require.register("interfaces/index.js", function(module, exports, require){ - -exports.bdd = require('./bdd'); -exports.tdd = require('./tdd'); -exports.qunit = require('./qunit'); -exports.exports = require('./exports'); - -}); // module: interfaces/index.js - -require.register("interfaces/qunit.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Suite = require('../suite') - , Test = require('../test'); - -/** - * QUnit-style interface: - * - * suite('Array'); - * - * test('#length', function(){ - * var arr = [1,2,3]; - * ok(arr.length == 3); - * }); - * - * test('#indexOf()', function(){ - * var arr = [1,2,3]; - * ok(arr.indexOf(1) == 0); - * ok(arr.indexOf(2) == 1); - * ok(arr.indexOf(3) == 2); - * }); - * - * suite('String'); - * - * test('#length', function(){ - * ok('foo'.length == 3); - * }); - * - */ - -module.exports = function(suite){ - var suites = [suite]; - - suite.on('pre-require', function(context, file, mocha){ - - /** - * Execute before running tests. - */ - - context.before = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after running tests. - */ - - context.after = function(fn){ - suites[0].afterAll(fn); - }; - - /** - * Execute before each test case. - */ - - context.beforeEach = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.afterEach = function(fn){ - suites[0].afterEach(fn); - }; - - /** - * Describe a "suite" with the given `title`. - */ - - context.suite = function(title){ - if (suites.length > 1) suites.shift(); - var suite = Suite.create(suites[0], title); - suites.unshift(suite); - return suite; - }; - - /** - * Exclusive test-case. - */ - - context.suite.only = function(title, fn){ - var suite = context.suite(title, fn); - mocha.grep(suite.fullTitle()); - }; - - /** - * Describe a specification or test-case - * with the given `title` and callback `fn` - * acting as a thunk. - */ - - context.test = function(title, fn){ - var test = new Test(title, fn); - suites[0].addTest(test); - return test; - }; - - /** - * Exclusive test-case. - */ - - context.test.only = function(title, fn){ - var test = context.test(title, fn); - mocha.grep(test.fullTitle()); - }; - - /** - * Pending test case. - */ - - context.test.skip = function(title){ - context.test(title); - }; - }); -}; - -}); // module: interfaces/qunit.js - -require.register("interfaces/tdd.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Suite = require('../suite') - , Test = require('../test'); - -/** - * TDD-style interface: - * - * suite('Array', function(){ - * suite('#indexOf()', function(){ - * suiteSetup(function(){ - * - * }); - * - * test('should return -1 when not present', function(){ - * - * }); - * - * test('should return the index when present', function(){ - * - * }); - * - * suiteTeardown(function(){ - * - * }); - * }); - * }); - * - */ - -module.exports = function(suite){ - var suites = [suite]; - - suite.on('pre-require', function(context, file, mocha){ - - /** - * Execute before each test case. - */ - - context.setup = function(fn){ - suites[0].beforeEach(fn); - }; - - /** - * Execute after each test case. - */ - - context.teardown = function(fn){ - suites[0].afterEach(fn); - }; - - /** - * Execute before the suite. - */ - - context.suiteSetup = function(fn){ - suites[0].beforeAll(fn); - }; - - /** - * Execute after the suite. - */ - - context.suiteTeardown = function(fn){ - suites[0].afterAll(fn); - }; - - /** - * Describe a "suite" with the given `title` - * and callback `fn` containing nested suites - * and/or tests. - */ - - context.suite = function(title, fn){ - var suite = Suite.create(suites[0], title); - suites.unshift(suite); - fn.call(suite); - suites.shift(); - return suite; - }; - - /** - * Pending suite. - */ - context.suite.skip = function(title, fn) { - var suite = Suite.create(suites[0], title); - suite.pending = true; - suites.unshift(suite); - fn.call(suite); - suites.shift(); - }; - - /** - * Exclusive test-case. - */ - - context.suite.only = function(title, fn){ - var suite = context.suite(title, fn); - mocha.grep(suite.fullTitle()); - }; - - /** - * Describe a specification or test-case - * with the given `title` and callback `fn` - * acting as a thunk. - */ - - context.test = function(title, fn){ - var suite = suites[0]; - if (suite.pending) var fn = null; - var test = new Test(title, fn); - suite.addTest(test); - return test; - }; - - /** - * Exclusive test-case. - */ - - context.test.only = function(title, fn){ - var test = context.test(title, fn); - mocha.grep(test.fullTitle()); - }; - - /** - * Pending test case. - */ - - context.test.skip = function(title){ - context.test(title); - }; - }); -}; - -}); // module: interfaces/tdd.js - -require.register("mocha.js", function(module, exports, require){ -/*! - * mocha - * Copyright(c) 2011 TJ Holowaychuk - * MIT Licensed - */ - -/** - * Module dependencies. - */ - -var path = require('browser/path') - , utils = require('./utils'); - -/** - * Expose `Mocha`. - */ - -exports = module.exports = Mocha; - -/** - * Expose internals. - */ - -exports.utils = utils; -exports.interfaces = require('./interfaces'); -exports.reporters = require('./reporters'); -exports.Runnable = require('./runnable'); -exports.Context = require('./context'); -exports.Runner = require('./runner'); -exports.Suite = require('./suite'); -exports.Hook = require('./hook'); -exports.Test = require('./test'); - -/** - * Return image `name` path. - * - * @param {String} name - * @return {String} - * @api private - */ - -function image(name) { - return __dirname + '/../images/' + name + '.png'; -} - -/** - * Setup mocha with `options`. - * - * Options: - * - * - `ui` name "bdd", "tdd", "exports" etc - * - `reporter` reporter instance, defaults to `mocha.reporters.Dot` - * - `globals` array of accepted globals - * - `timeout` timeout in milliseconds - * - `bail` bail on the first test failure - * - `slow` milliseconds to wait before considering a test slow - * - `ignoreLeaks` ignore global leaks - * - `grep` string or regexp to filter tests with - * - * @param {Object} options - * @api public - */ - -function Mocha(options) { - options = options || {}; - this.files = []; - this.options = options; - this.grep(options.grep); - this.suite = new exports.Suite('', new exports.Context); - this.ui(options.ui); - this.bail(options.bail); - this.reporter(options.reporter); - if (options.timeout) this.timeout(options.timeout); - if (options.slow) this.slow(options.slow); -} - -/** - * Enable or disable bailing on the first failure. - * - * @param {Boolean} [bail] - * @api public - */ - -Mocha.prototype.bail = function(bail){ - if (0 == arguments.length) bail = true; - this.suite.bail(bail); - return this; -}; - -/** - * Add test `file`. - * - * @param {String} file - * @api public - */ - -Mocha.prototype.addFile = function(file){ - this.files.push(file); - return this; -}; - -/** - * Set reporter to `reporter`, defaults to "dot". - * - * @param {String|Function} reporter name or constructor - * @api public - */ - -Mocha.prototype.reporter = function(reporter){ - if ('function' == typeof reporter) { - this._reporter = reporter; - } else { - reporter = reporter || 'dot'; - try { - this._reporter = require('./reporters/' + reporter); - } catch (err) { - this._reporter = require(reporter); - } - if (!this._reporter) throw new Error('invalid reporter "' + reporter + '"'); - } - return this; -}; - -/** - * Set test UI `name`, defaults to "bdd". - * - * @param {String} bdd - * @api public - */ - -Mocha.prototype.ui = function(name){ - name = name || 'bdd'; - this._ui = exports.interfaces[name]; - if (!this._ui) throw new Error('invalid interface "' + name + '"'); - this._ui = this._ui(this.suite); - return this; -}; - -/** - * Load registered files. - * - * @api private - */ - -Mocha.prototype.loadFiles = function(fn){ - var self = this; - var suite = this.suite; - var pending = this.files.length; - this.files.forEach(function(file){ - file = path.resolve(file); - suite.emit('pre-require', global, file, self); - suite.emit('require', require(file), file, self); - suite.emit('post-require', global, file, self); - --pending || (fn && fn()); - }); -}; - -/** - * Enable growl support. - * - * @api private - */ - -Mocha.prototype._growl = function(runner, reporter) { - var notify = require('growl'); - - runner.on('end', function(){ - var stats = reporter.stats; - if (stats.failures) { - var msg = stats.failures + ' of ' + runner.total + ' tests failed'; - notify(msg, { name: 'mocha', title: 'Failed', image: image('error') }); - } else { - notify(stats.passes + ' tests passed in ' + stats.duration + 'ms', { - name: 'mocha' - , title: 'Passed' - , image: image('ok') - }); - } - }); -}; - -/** - * Add regexp to grep, if `re` is a string it is escaped. - * - * @param {RegExp|String} re - * @return {Mocha} - * @api public - */ - -Mocha.prototype.grep = function(re){ - this.options.grep = 'string' == typeof re - ? new RegExp(utils.escapeRegexp(re)) - : re; - return this; -}; - -/** - * Invert `.grep()` matches. - * - * @return {Mocha} - * @api public - */ - -Mocha.prototype.invert = function(){ - this.options.invert = true; - return this; -}; - -/** - * Ignore global leaks. - * - * @param {Boolean} ignore - * @return {Mocha} - * @api public - */ - -Mocha.prototype.ignoreLeaks = function(ignore){ - this.options.ignoreLeaks = !!ignore; - return this; -}; - -/** - * Enable global leak checking. - * - * @return {Mocha} - * @api public - */ - -Mocha.prototype.checkLeaks = function(){ - this.options.ignoreLeaks = false; - return this; -}; - -/** - * Enable growl support. - * - * @return {Mocha} - * @api public - */ - -Mocha.prototype.growl = function(){ - this.options.growl = true; - return this; -}; - -/** - * Ignore `globals` array or string. - * - * @param {Array|String} globals - * @return {Mocha} - * @api public - */ - -Mocha.prototype.globals = function(globals){ - this.options.globals = (this.options.globals || []).concat(globals); - return this; -}; - -/** - * Set the timeout in milliseconds. - * - * @param {Number} timeout - * @return {Mocha} - * @api public - */ - -Mocha.prototype.timeout = function(timeout){ - this.suite.timeout(timeout); - return this; -}; - -/** - * Set slowness threshold in milliseconds. - * - * @param {Number} slow - * @return {Mocha} - * @api public - */ - -Mocha.prototype.slow = function(slow){ - this.suite.slow(slow); - return this; -}; - -/** - * Makes all tests async (accepting a callback) - * - * @return {Mocha} - * @api public - */ - -Mocha.prototype.asyncOnly = function(){ - this.options.asyncOnly = true; - return this; -}; - -/** - * Run tests and invoke `fn()` when complete. - * - * @param {Function} fn - * @return {Runner} - * @api public - */ - -Mocha.prototype.run = function(fn){ - if (this.files.length) this.loadFiles(); - var suite = this.suite; - var options = this.options; - var runner = new exports.Runner(suite); - var reporter = new this._reporter(runner); - runner.ignoreLeaks = false !== options.ignoreLeaks; - runner.asyncOnly = options.asyncOnly; - if (options.grep) runner.grep(options.grep, options.invert); - if (options.globals) runner.globals(options.globals); - if (options.growl) this._growl(runner, reporter); - return runner.run(fn); -}; - -}); // module: mocha.js - -require.register("ms.js", function(module, exports, require){ - -/** - * Helpers. - */ - -var s = 1000; -var m = s * 60; -var h = m * 60; -var d = h * 24; - -/** - * Parse or format the given `val`. - * - * @param {String|Number} val - * @return {String|Number} - * @api public - */ - -module.exports = function(val){ - if ('string' == typeof val) return parse(val); - return format(val); -} - -/** - * Parse the given `str` and return milliseconds. - * - * @param {String} str - * @return {Number} - * @api private - */ - -function parse(str) { - var m = /^((?:\d+)?\.?\d+) *(ms|seconds?|s|minutes?|m|hours?|h|days?|d|years?|y)?$/i.exec(str); - if (!m) return; - var n = parseFloat(m[1]); - var type = (m[2] || 'ms').toLowerCase(); - switch (type) { - case 'years': - case 'year': - case 'y': - return n * 31557600000; - case 'days': - case 'day': - case 'd': - return n * 86400000; - case 'hours': - case 'hour': - case 'h': - return n * 3600000; - case 'minutes': - case 'minute': - case 'm': - return n * 60000; - case 'seconds': - case 'second': - case 's': - return n * 1000; - case 'ms': - return n; - } -} - -/** - * Format the given `ms`. - * - * @param {Number} ms - * @return {String} - * @api public - */ - -function format(ms) { - if (ms == d) return Math.round(ms / d) + ' day'; - if (ms > d) return Math.round(ms / d) + ' days'; - if (ms == h) return Math.round(ms / h) + ' hour'; - if (ms > h) return Math.round(ms / h) + ' hours'; - if (ms == m) return Math.round(ms / m) + ' minute'; - if (ms > m) return Math.round(ms / m) + ' minutes'; - if (ms == s) return Math.round(ms / s) + ' second'; - if (ms > s) return Math.round(ms / s) + ' seconds'; - return ms + ' ms'; -} -}); // module: ms.js - -require.register("reporters/base.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var tty = require('browser/tty') - , diff = require('browser/diff') - , ms = require('../ms'); - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date - , setTimeout = global.setTimeout - , setInterval = global.setInterval - , clearTimeout = global.clearTimeout - , clearInterval = global.clearInterval; - -/** - * Check if both stdio streams are associated with a tty. - */ - -var isatty = tty.isatty(1) && tty.isatty(2); - -/** - * Expose `Base`. - */ - -exports = module.exports = Base; - -/** - * Enable coloring by default. - */ - -exports.useColors = isatty; - -/** - * Default color map. - */ - -exports.colors = { - 'pass': 90 - , 'fail': 31 - , 'bright pass': 92 - , 'bright fail': 91 - , 'bright yellow': 93 - , 'pending': 36 - , 'suite': 0 - , 'error title': 0 - , 'error message': 31 - , 'error stack': 90 - , 'checkmark': 32 - , 'fast': 90 - , 'medium': 33 - , 'slow': 31 - , 'green': 32 - , 'light': 90 - , 'diff gutter': 90 - , 'diff added': 42 - , 'diff removed': 41 -}; - -/** - * Default symbol map. - */ - -exports.symbols = { - ok: '✓', - err: '✖', - dot: '․' -}; - -// With node.js on Windows: use symbols available in terminal default fonts -if ('win32' == process.platform) { - exports.symbols.ok = '\u221A'; - exports.symbols.err = '\u00D7'; - exports.symbols.dot = '.'; -} - -/** - * Color `str` with the given `type`, - * allowing colors to be disabled, - * as well as user-defined color - * schemes. - * - * @param {String} type - * @param {String} str - * @return {String} - * @api private - */ - -var color = exports.color = function(type, str) { - if (!exports.useColors) return str; - return '\u001b[' + exports.colors[type] + 'm' + str + '\u001b[0m'; -}; - -/** - * Expose term window size, with some - * defaults for when stderr is not a tty. - */ - -exports.window = { - width: isatty - ? process.stdout.getWindowSize - ? process.stdout.getWindowSize(1)[0] - : tty.getWindowSize()[1] - : 75 -}; - -/** - * Expose some basic cursor interactions - * that are common among reporters. - */ - -exports.cursor = { - hide: function(){ - process.stdout.write('\u001b[?25l'); - }, - - show: function(){ - process.stdout.write('\u001b[?25h'); - }, - - deleteLine: function(){ - process.stdout.write('\u001b[2K'); - }, - - beginningOfLine: function(){ - process.stdout.write('\u001b[0G'); - }, - - CR: function(){ - exports.cursor.deleteLine(); - exports.cursor.beginningOfLine(); - } -}; - -/** - * Outut the given `failures` as a list. - * - * @param {Array} failures - * @api public - */ - -exports.list = function(failures){ - console.error(); - failures.forEach(function(test, i){ - // format - var fmt = color('error title', ' %s) %s:\n') - + color('error message', ' %s') - + color('error stack', '\n%s\n'); - - // msg - var err = test.err - , message = err.message || '' - , stack = err.stack || message - , index = stack.indexOf(message) + message.length - , msg = stack.slice(0, index) - , actual = err.actual - , expected = err.expected - , escape = true; - - // uncaught - if (err.uncaught) { - msg = 'Uncaught ' + msg; - } - - // explicitly show diff - if (err.showDiff && sameType(actual, expected)) { - escape = false; - err.actual = actual = stringify(actual); - err.expected = expected = stringify(expected); - } - - // actual / expected diff - if ('string' == typeof actual && 'string' == typeof expected) { - msg = errorDiff(err, 'Words', escape); - - // linenos - var lines = msg.split('\n'); - if (lines.length > 4) { - var width = String(lines.length).length; - msg = lines.map(function(str, i){ - return pad(++i, width) + ' |' + ' ' + str; - }).join('\n'); - } - - // legend - msg = '\n' - + color('diff removed', 'actual') - + ' ' - + color('diff added', 'expected') - + '\n\n' - + msg - + '\n'; - - // indent - msg = msg.replace(/^/gm, ' '); - - fmt = color('error title', ' %s) %s:\n%s') - + color('error stack', '\n%s\n'); - } - - // indent stack trace without msg - stack = stack.slice(index ? index + 1 : index) - .replace(/^/gm, ' '); - - console.error(fmt, (i + 1), test.fullTitle(), msg, stack); - }); -}; - -/** - * Initialize a new `Base` reporter. - * - * All other reporters generally - * inherit from this reporter, providing - * stats such as test duration, number - * of tests passed / failed etc. - * - * @param {Runner} runner - * @api public - */ - -function Base(runner) { - var self = this - , stats = this.stats = { suites: 0, tests: 0, passes: 0, pending: 0, failures: 0 } - , failures = this.failures = []; - - if (!runner) return; - this.runner = runner; - - runner.stats = stats; - - runner.on('start', function(){ - stats.start = new Date; - }); - - runner.on('suite', function(suite){ - stats.suites = stats.suites || 0; - suite.root || stats.suites++; - }); - - runner.on('test end', function(test){ - stats.tests = stats.tests || 0; - stats.tests++; - }); - - runner.on('pass', function(test){ - stats.passes = stats.passes || 0; - - var medium = test.slow() / 2; - test.speed = test.duration > test.slow() - ? 'slow' - : test.duration > medium - ? 'medium' - : 'fast'; - - stats.passes++; - }); - - runner.on('fail', function(test, err){ - stats.failures = stats.failures || 0; - stats.failures++; - test.err = err; - failures.push(test); - }); - - runner.on('end', function(){ - stats.end = new Date; - stats.duration = new Date - stats.start; - }); - - runner.on('pending', function(){ - stats.pending++; - }); -} - -/** - * Output common epilogue used by many of - * the bundled reporters. - * - * @api public - */ - -Base.prototype.epilogue = function(){ - var stats = this.stats; - var tests; - var fmt; - - console.log(); - - // passes - fmt = color('bright pass', ' ') - + color('green', ' %d passing') - + color('light', ' (%s)'); - - console.log(fmt, - stats.passes || 0, - ms(stats.duration)); - - // pending - if (stats.pending) { - fmt = color('pending', ' ') - + color('pending', ' %d pending'); - - console.log(fmt, stats.pending); - } - - // failures - if (stats.failures) { - fmt = color('fail', ' %d failing'); - - console.error(fmt, - stats.failures); - - Base.list(this.failures); - console.error(); - } - - console.log(); -}; - -/** - * Pad the given `str` to `len`. - * - * @param {String} str - * @param {String} len - * @return {String} - * @api private - */ - -function pad(str, len) { - str = String(str); - return Array(len - str.length + 1).join(' ') + str; -} - -/** - * Return a character diff for `err`. - * - * @param {Error} err - * @return {String} - * @api private - */ - -function errorDiff(err, type, escape) { - return diff['diff' + type](err.actual, err.expected).map(function(str){ - if (escape) { - str.value = str.value - .replace(/\t/g, '') - .replace(/\r/g, '') - .replace(/\n/g, '\n'); - } - if (str.added) return colorLines('diff added', str.value); - if (str.removed) return colorLines('diff removed', str.value); - return str.value; - }).join(''); -} - -/** - * Color lines for `str`, using the color `name`. - * - * @param {String} name - * @param {String} str - * @return {String} - * @api private - */ - -function colorLines(name, str) { - return str.split('\n').map(function(str){ - return color(name, str); - }).join('\n'); -} - -/** - * Stringify `obj`. - * - * @param {Mixed} obj - * @return {String} - * @api private - */ - -function stringify(obj) { - if (obj instanceof RegExp) return obj.toString(); - return JSON.stringify(obj, null, 2); -} - -/** - * Check that a / b have the same type. - * - * @param {Object} a - * @param {Object} b - * @return {Boolean} - * @api private - */ - -function sameType(a, b) { - a = Object.prototype.toString.call(a); - b = Object.prototype.toString.call(b); - return a == b; -} - -}); // module: reporters/base.js - -require.register("reporters/doc.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , utils = require('../utils'); - -/** - * Expose `Doc`. - */ - -exports = module.exports = Doc; - -/** - * Initialize a new `Doc` reporter. - * - * @param {Runner} runner - * @api public - */ - -function Doc(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , total = runner.total - , indents = 2; - - function indent() { - return Array(indents).join(' '); - } - - runner.on('suite', function(suite){ - if (suite.root) return; - ++indents; - console.log('%s
    ', indent()); - ++indents; - console.log('%s

    %s

    ', indent(), utils.escape(suite.title)); - console.log('%s
    ', indent()); - }); - - runner.on('suite end', function(suite){ - if (suite.root) return; - console.log('%s
    ', indent()); - --indents; - console.log('%s
    ', indent()); - --indents; - }); - - runner.on('pass', function(test){ - console.log('%s
    %s
    ', indent(), utils.escape(test.title)); - var code = utils.escape(utils.clean(test.fn.toString())); - console.log('%s
    %s
    ', indent(), code); - }); -} - -}); // module: reporters/doc.js - -require.register("reporters/dot.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , color = Base.color; - -/** - * Expose `Dot`. - */ - -exports = module.exports = Dot; - -/** - * Initialize a new `Dot` matrix test reporter. - * - * @param {Runner} runner - * @api public - */ - -function Dot(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , width = Base.window.width * .75 | 0 - , n = 0; - - runner.on('start', function(){ - process.stdout.write('\n '); - }); - - runner.on('pending', function(test){ - process.stdout.write(color('pending', Base.symbols.dot)); - }); - - runner.on('pass', function(test){ - if (++n % width == 0) process.stdout.write('\n '); - if ('slow' == test.speed) { - process.stdout.write(color('bright yellow', Base.symbols.dot)); - } else { - process.stdout.write(color(test.speed, Base.symbols.dot)); - } - }); - - runner.on('fail', function(test, err){ - if (++n % width == 0) process.stdout.write('\n '); - process.stdout.write(color('fail', Base.symbols.dot)); - }); - - runner.on('end', function(){ - console.log(); - self.epilogue(); - }); -} - -/** - * Inherit from `Base.prototype`. - */ - -function F(){}; -F.prototype = Base.prototype; -Dot.prototype = new F; -Dot.prototype.constructor = Dot; - -}); // module: reporters/dot.js - -require.register("reporters/html-cov.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var JSONCov = require('./json-cov') - , fs = require('browser/fs'); - -/** - * Expose `HTMLCov`. - */ - -exports = module.exports = HTMLCov; - -/** - * Initialize a new `JsCoverage` reporter. - * - * @param {Runner} runner - * @api public - */ - -function HTMLCov(runner) { - var jade = require('jade') - , file = __dirname + '/templates/coverage.jade' - , str = fs.readFileSync(file, 'utf8') - , fn = jade.compile(str, { filename: file }) - , self = this; - - JSONCov.call(this, runner, false); - - runner.on('end', function(){ - process.stdout.write(fn({ - cov: self.cov - , coverageClass: coverageClass - })); - }); -} - -/** - * Return coverage class for `n`. - * - * @return {String} - * @api private - */ - -function coverageClass(n) { - if (n >= 75) return 'high'; - if (n >= 50) return 'medium'; - if (n >= 25) return 'low'; - return 'terrible'; -} -}); // module: reporters/html-cov.js - -require.register("reporters/html.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , utils = require('../utils') - , Progress = require('../browser/progress') - , escape = utils.escape; - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date - , setTimeout = global.setTimeout - , setInterval = global.setInterval - , clearTimeout = global.clearTimeout - , clearInterval = global.clearInterval; - -/** - * Expose `Doc`. - */ - -exports = module.exports = HTML; - - -/** - * Stats template. - */ - -var statsTemplate = ''; - -/** - * Initialize a new `Doc` reporter. - * - * @param {Runner} runner - * @api public - */ - -function HTML(runner, root) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , total = runner.total - , stat = fragment(statsTemplate) - , items = stat.getElementsByTagName('li') - , passes = items[1].getElementsByTagName('em')[0] - , passesLink = items[1].getElementsByTagName('a')[0] - , pending = items[2].getElementsByTagName('em')[0] - , pendingLink = items[2].getElementsByTagName('a')[0] - , failures = items[3].getElementsByTagName('em')[0] - , failuresLink = items[3].getElementsByTagName('a')[0] - , duration = items[4].getElementsByTagName('em')[0] - , canvas = stat.getElementsByTagName('canvas')[0] - , report = fragment('
      ') - , stack = [report] - , progress - , ctx - - root = root || document.getElementById('mocha'); - - if (canvas.getContext) { - var ratio = window.devicePixelRatio || 1; - canvas.style.width = canvas.width; - canvas.style.height = canvas.height; - canvas.width *= ratio; - canvas.height *= ratio; - ctx = canvas.getContext('2d'); - ctx.scale(ratio, ratio); - progress = new Progress; - } - - if (!root) return error('#mocha div missing, add it to your document'); - - // pass toggle - on(passesLink, 'click', function(){ - unhide(); - var name = /pass/.test(report.className) ? '' : ' pass'; - report.className = report.className.replace(/fail|pass|pending/g, '') + name; - if (report.className.trim()) hideSuitesWithout('test pass'); - }); - - // pending toggle - on(pendingLink, 'click', function(){ - unhide(); - var name = /pending/.test(report.className) ? '' : ' pending'; - report.className = report.className.replace(/fail|pass|pending/g, '') + name; - if (report.className.trim()) hideSuitesWithout('test pending'); - }); - - // failure toggle - on(failuresLink, 'click', function(){ - unhide(); - var name = /fail/.test(report.className) ? '' : ' fail'; - report.className = report.className.replace(/fail|pass|pending/g, '') + name; - if (report.className.trim()) hideSuitesWithout('test fail'); - }); - - root.appendChild(stat); - root.appendChild(report); - - if (progress) progress.size(40); - - runner.on('suite', function(suite){ - if (suite.root) return; - - // suite - var url = '?grep=' + encodeURIComponent(suite.fullTitle()); - var el = fragment('
    • %s

    • ', url, escape(suite.title)); - - // container - stack[0].appendChild(el); - stack.unshift(document.createElement('ul')); - el.appendChild(stack[0]); - }); - - runner.on('suite end', function(suite){ - if (suite.root) return; - stack.shift(); - }); - - runner.on('fail', function(test, err){ - if ('hook' == test.type) runner.emit('test end', test); - }); - - runner.on('test end', function(test){ - // TODO: add to stats - var percent = stats.tests / this.total * 100 | 0; - if (progress) progress.update(percent).draw(ctx); - - // update stats - var ms = new Date - stats.start; - text(passes, stats.passes); - text(failures, stats.failures); - text(pending, stats.pending); - text(duration, (ms / 1000).toFixed(2)); - - // test - if ('passed' == test.state) { - var el = fragment('
    • %e%ems

    • ', test.speed, test.title, test.duration, encodeURIComponent(test.fullTitle())); - } else if (test.pending) { - var el = fragment('
    • %e

    • ', test.title); - } else { - var el = fragment('
    • %e

    • ', test.title, encodeURIComponent(test.fullTitle())); - var str = test.err.stack || test.err.toString(); - - // FF / Opera do not add the message - if (!~str.indexOf(test.err.message)) { - str = test.err.message + '\n' + str; - } - - // <=IE7 stringifies to [Object Error]. Since it can be overloaded, we - // check for the result of the stringifying. - if ('[object Error]' == str) str = test.err.message; - - // Safari doesn't give you a stack. Let's at least provide a source line. - if (!test.err.stack && test.err.sourceURL && test.err.line !== undefined) { - str += "\n(" + test.err.sourceURL + ":" + test.err.line + ")"; - } - - el.appendChild(fragment('
      %e
      ', str)); - } - - // toggle code - // TODO: defer - if (!test.pending) { - var h2 = el.getElementsByTagName('h2')[0]; - - on(h2, 'click', function(){ - pre.style.display = 'none' == pre.style.display - ? 'block' - : 'none'; - }); - - var pre = fragment('
      %e
      ', utils.clean(test.fn.toString())); - el.appendChild(pre); - pre.style.display = 'none'; - } - - // Don't call .appendChild if #mocha-report was already .shift()'ed off the stack. - if (stack[0]) stack[0].appendChild(el); - }); -} - -/** - * Display error `msg`. - */ - -function error(msg) { - document.body.appendChild(fragment('
      %s
      ', msg)); -} - -/** - * Return a DOM fragment from `html`. - */ - -function fragment(html) { - var args = arguments - , div = document.createElement('div') - , i = 1; - - div.innerHTML = html.replace(/%([se])/g, function(_, type){ - switch (type) { - case 's': return String(args[i++]); - case 'e': return escape(args[i++]); - } - }); - - return div.firstChild; -} - -/** - * Check for suites that do not have elements - * with `classname`, and hide them. - */ - -function hideSuitesWithout(classname) { - var suites = document.getElementsByClassName('suite'); - for (var i = 0; i < suites.length; i++) { - var els = suites[i].getElementsByClassName(classname); - if (0 == els.length && !/hidden/.test(suites[i].className)) suites[i].className += ' hidden'; - } -} - -/** - * Unhide .hidden suites. - */ - -function unhide() { - var els = document.getElementsByClassName('suite'); - for (var i = 0; i < els.length; ++i) { - els[i].className = els[i].className.replace('suite hidden', 'suite'); - } -} - -/** - * Set `el` text to `str`. - */ - -function text(el, str) { - if (el.textContent) { - el.textContent = str; - } else { - el.innerText = str; - } -} - -/** - * Listen on `event` with callback `fn`. - */ - -function on(el, event, fn) { - if (el.addEventListener) { - el.addEventListener(event, fn, false); - } else { - el.attachEvent('on' + event, fn); - } -} - -}); // module: reporters/html.js - -require.register("reporters/index.js", function(module, exports, require){ - -exports.Base = require('./base'); -exports.Dot = require('./dot'); -exports.Doc = require('./doc'); -exports.TAP = require('./tap'); -exports.JSON = require('./json'); -exports.HTML = require('./html'); -exports.List = require('./list'); -exports.Min = require('./min'); -exports.Spec = require('./spec'); -exports.Nyan = require('./nyan'); -exports.XUnit = require('./xunit'); -exports.Markdown = require('./markdown'); -exports.Progress = require('./progress'); -exports.Landing = require('./landing'); -exports.JSONCov = require('./json-cov'); -exports.HTMLCov = require('./html-cov'); -exports.JSONStream = require('./json-stream'); -exports.Teamcity = require('./teamcity'); - -}); // module: reporters/index.js - -require.register("reporters/json-cov.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base'); - -/** - * Expose `JSONCov`. - */ - -exports = module.exports = JSONCov; - -/** - * Initialize a new `JsCoverage` reporter. - * - * @param {Runner} runner - * @param {Boolean} output - * @api public - */ - -function JSONCov(runner, output) { - var self = this - , output = 1 == arguments.length ? true : output; - - Base.call(this, runner); - - var tests = [] - , failures = [] - , passes = []; - - runner.on('test end', function(test){ - tests.push(test); - }); - - runner.on('pass', function(test){ - passes.push(test); - }); - - runner.on('fail', function(test){ - failures.push(test); - }); - - runner.on('end', function(){ - var cov = global._$jscoverage || {}; - var result = self.cov = map(cov); - result.stats = self.stats; - result.tests = tests.map(clean); - result.failures = failures.map(clean); - result.passes = passes.map(clean); - if (!output) return; - process.stdout.write(JSON.stringify(result, null, 2 )); - }); -} - -/** - * Map jscoverage data to a JSON structure - * suitable for reporting. - * - * @param {Object} cov - * @return {Object} - * @api private - */ - -function map(cov) { - var ret = { - instrumentation: 'node-jscoverage' - , sloc: 0 - , hits: 0 - , misses: 0 - , coverage: 0 - , files: [] - }; - - for (var filename in cov) { - var data = coverage(filename, cov[filename]); - ret.files.push(data); - ret.hits += data.hits; - ret.misses += data.misses; - ret.sloc += data.sloc; - } - - ret.files.sort(function(a, b) { - return a.filename.localeCompare(b.filename); - }); - - if (ret.sloc > 0) { - ret.coverage = (ret.hits / ret.sloc) * 100; - } - - return ret; -}; - -/** - * Map jscoverage data for a single source file - * to a JSON structure suitable for reporting. - * - * @param {String} filename name of the source file - * @param {Object} data jscoverage coverage data - * @return {Object} - * @api private - */ - -function coverage(filename, data) { - var ret = { - filename: filename, - coverage: 0, - hits: 0, - misses: 0, - sloc: 0, - source: {} - }; - - data.source.forEach(function(line, num){ - num++; - - if (data[num] === 0) { - ret.misses++; - ret.sloc++; - } else if (data[num] !== undefined) { - ret.hits++; - ret.sloc++; - } - - ret.source[num] = { - source: line - , coverage: data[num] === undefined - ? '' - : data[num] - }; - }); - - ret.coverage = ret.hits / ret.sloc * 100; - - return ret; -} - -/** - * Return a plain-object representation of `test` - * free of cyclic properties etc. - * - * @param {Object} test - * @return {Object} - * @api private - */ - -function clean(test) { - return { - title: test.title - , fullTitle: test.fullTitle() - , duration: test.duration - } -} - -}); // module: reporters/json-cov.js - -require.register("reporters/json-stream.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , color = Base.color; - -/** - * Expose `List`. - */ - -exports = module.exports = List; - -/** - * Initialize a new `List` test reporter. - * - * @param {Runner} runner - * @api public - */ - -function List(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , total = runner.total; - - runner.on('start', function(){ - console.log(JSON.stringify(['start', { total: total }])); - }); - - runner.on('pass', function(test){ - console.log(JSON.stringify(['pass', clean(test)])); - }); - - runner.on('fail', function(test, err){ - console.log(JSON.stringify(['fail', clean(test)])); - }); - - runner.on('end', function(){ - process.stdout.write(JSON.stringify(['end', self.stats])); - }); -} - -/** - * Return a plain-object representation of `test` - * free of cyclic properties etc. - * - * @param {Object} test - * @return {Object} - * @api private - */ - -function clean(test) { - return { - title: test.title - , fullTitle: test.fullTitle() - , duration: test.duration - } -} -}); // module: reporters/json-stream.js - -require.register("reporters/json.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `JSON`. - */ - -exports = module.exports = JSONReporter; - -/** - * Initialize a new `JSON` reporter. - * - * @param {Runner} runner - * @api public - */ - -function JSONReporter(runner) { - var self = this; - Base.call(this, runner); - - var tests = [] - , failures = [] - , passes = []; - - runner.on('test end', function(test){ - tests.push(test); - }); - - runner.on('pass', function(test){ - passes.push(test); - }); - - runner.on('fail', function(test){ - failures.push(test); - }); - - runner.on('end', function(){ - var obj = { - stats: self.stats - , tests: tests.map(clean) - , failures: failures.map(clean) - , passes: passes.map(clean) - }; - - process.stdout.write(JSON.stringify(obj, null, 2)); - }); -} - -/** - * Return a plain-object representation of `test` - * free of cyclic properties etc. - * - * @param {Object} test - * @return {Object} - * @api private - */ - -function clean(test) { - return { - title: test.title - , fullTitle: test.fullTitle() - , duration: test.duration - } -} -}); // module: reporters/json.js - -require.register("reporters/landing.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `Landing`. - */ - -exports = module.exports = Landing; - -/** - * Airplane color. - */ - -Base.colors.plane = 0; - -/** - * Airplane crash color. - */ - -Base.colors['plane crash'] = 31; - -/** - * Runway color. - */ - -Base.colors.runway = 90; - -/** - * Initialize a new `Landing` reporter. - * - * @param {Runner} runner - * @api public - */ - -function Landing(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , width = Base.window.width * .75 | 0 - , total = runner.total - , stream = process.stdout - , plane = color('plane', '✈') - , crashed = -1 - , n = 0; - - function runway() { - var buf = Array(width).join('-'); - return ' ' + color('runway', buf); - } - - runner.on('start', function(){ - stream.write('\n '); - cursor.hide(); - }); - - runner.on('test end', function(test){ - // check if the plane crashed - var col = -1 == crashed - ? width * ++n / total | 0 - : crashed; - - // show the crash - if ('failed' == test.state) { - plane = color('plane crash', '✈'); - crashed = col; - } - - // render landing strip - stream.write('\u001b[4F\n\n'); - stream.write(runway()); - stream.write('\n '); - stream.write(color('runway', Array(col).join('⋅'))); - stream.write(plane) - stream.write(color('runway', Array(width - col).join('⋅') + '\n')); - stream.write(runway()); - stream.write('\u001b[0m'); - }); - - runner.on('end', function(){ - cursor.show(); - console.log(); - self.epilogue(); - }); -} - -/** - * Inherit from `Base.prototype`. - */ - -function F(){}; -F.prototype = Base.prototype; -Landing.prototype = new F; -Landing.prototype.constructor = Landing; - -}); // module: reporters/landing.js - -require.register("reporters/list.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `List`. - */ - -exports = module.exports = List; - -/** - * Initialize a new `List` test reporter. - * - * @param {Runner} runner - * @api public - */ - -function List(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , n = 0; - - runner.on('start', function(){ - console.log(); - }); - - runner.on('test', function(test){ - process.stdout.write(color('pass', ' ' + test.fullTitle() + ': ')); - }); - - runner.on('pending', function(test){ - var fmt = color('checkmark', ' -') - + color('pending', ' %s'); - console.log(fmt, test.fullTitle()); - }); - - runner.on('pass', function(test){ - var fmt = color('checkmark', ' '+Base.symbols.dot) - + color('pass', ' %s: ') - + color(test.speed, '%dms'); - cursor.CR(); - console.log(fmt, test.fullTitle(), test.duration); - }); - - runner.on('fail', function(test, err){ - cursor.CR(); - console.log(color('fail', ' %d) %s'), ++n, test.fullTitle()); - }); - - runner.on('end', self.epilogue.bind(self)); -} - -/** - * Inherit from `Base.prototype`. - */ - -function F(){}; -F.prototype = Base.prototype; -List.prototype = new F; -List.prototype.constructor = List; - - -}); // module: reporters/list.js - -require.register("reporters/markdown.js", function(module, exports, require){ -/** - * Module dependencies. - */ - -var Base = require('./base') - , utils = require('../utils'); - -/** - * Expose `Markdown`. - */ - -exports = module.exports = Markdown; - -/** - * Initialize a new `Markdown` reporter. - * - * @param {Runner} runner - * @api public - */ - -function Markdown(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , level = 0 - , buf = ''; - - function title(str) { - return Array(level).join('#') + ' ' + str; - } - - function indent() { - return Array(level).join(' '); - } - - function mapTOC(suite, obj) { - var ret = obj; - obj = obj[suite.title] = obj[suite.title] || { suite: suite }; - suite.suites.forEach(function(suite){ - mapTOC(suite, obj); - }); - return ret; - } - - function stringifyTOC(obj, level) { - ++level; - var buf = ''; - var link; - for (var key in obj) { - if ('suite' == key) continue; - if (key) link = ' - [' + key + '](#' + utils.slug(obj[key].suite.fullTitle()) + ')\n'; - if (key) buf += Array(level).join(' ') + link; - buf += stringifyTOC(obj[key], level); - } - --level; - return buf; - } - - function generateTOC(suite) { - var obj = mapTOC(suite, {}); - return stringifyTOC(obj, 0); - } - - generateTOC(runner.suite); - - runner.on('suite', function(suite){ - ++level; - var slug = utils.slug(suite.fullTitle()); - buf += '' + '\n'; - buf += title(suite.title) + '\n'; - }); - - runner.on('suite end', function(suite){ - --level; - }); - - runner.on('pass', function(test){ - var code = utils.clean(test.fn.toString()); - buf += test.title + '.\n'; - buf += '\n```js\n'; - buf += code + '\n'; - buf += '```\n\n'; - }); - - runner.on('end', function(){ - process.stdout.write('# TOC\n'); - process.stdout.write(generateTOC(runner.suite)); - process.stdout.write(buf); - }); -} -}); // module: reporters/markdown.js - -require.register("reporters/min.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base'); - -/** - * Expose `Min`. - */ - -exports = module.exports = Min; - -/** - * Initialize a new `Min` minimal test reporter (best used with --watch). - * - * @param {Runner} runner - * @api public - */ - -function Min(runner) { - Base.call(this, runner); - - runner.on('start', function(){ - // clear screen - process.stdout.write('\u001b[2J'); - // set cursor position - process.stdout.write('\u001b[1;3H'); - }); - - runner.on('end', this.epilogue.bind(this)); -} - -/** - * Inherit from `Base.prototype`. - */ - -function F(){}; -F.prototype = Base.prototype; -Min.prototype = new F; -Min.prototype.constructor = Min; - - -}); // module: reporters/min.js - -require.register("reporters/nyan.js", function(module, exports, require){ -/** - * Module dependencies. - */ - -var Base = require('./base') - , color = Base.color; - -/** - * Expose `Dot`. - */ - -exports = module.exports = NyanCat; - -/** - * Initialize a new `Dot` matrix test reporter. - * - * @param {Runner} runner - * @api public - */ - -function NyanCat(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , width = Base.window.width * .75 | 0 - , rainbowColors = this.rainbowColors = self.generateColors() - , colorIndex = this.colorIndex = 0 - , numerOfLines = this.numberOfLines = 4 - , trajectories = this.trajectories = [[], [], [], []] - , nyanCatWidth = this.nyanCatWidth = 11 - , trajectoryWidthMax = this.trajectoryWidthMax = (width - nyanCatWidth) - , scoreboardWidth = this.scoreboardWidth = 5 - , tick = this.tick = 0 - , n = 0; - - runner.on('start', function(){ - Base.cursor.hide(); - self.draw('start'); - }); - - runner.on('pending', function(test){ - self.draw('pending'); - }); - - runner.on('pass', function(test){ - self.draw('pass'); - }); - - runner.on('fail', function(test, err){ - self.draw('fail'); - }); - - runner.on('end', function(){ - Base.cursor.show(); - for (var i = 0; i < self.numberOfLines; i++) write('\n'); - self.epilogue(); - }); -} - -/** - * Draw the nyan cat with runner `status`. - * - * @param {String} status - * @api private - */ - -NyanCat.prototype.draw = function(status){ - this.appendRainbow(); - this.drawScoreboard(); - this.drawRainbow(); - this.drawNyanCat(status); - this.tick = !this.tick; -}; - -/** - * Draw the "scoreboard" showing the number - * of passes, failures and pending tests. - * - * @api private - */ - -NyanCat.prototype.drawScoreboard = function(){ - var stats = this.stats; - var colors = Base.colors; - - function draw(color, n) { - write(' '); - write('\u001b[' + color + 'm' + n + '\u001b[0m'); - write('\n'); - } - - draw(colors.green, stats.passes); - draw(colors.fail, stats.failures); - draw(colors.pending, stats.pending); - write('\n'); - - this.cursorUp(this.numberOfLines); -}; - -/** - * Append the rainbow. - * - * @api private - */ - -NyanCat.prototype.appendRainbow = function(){ - var segment = this.tick ? '_' : '-'; - var rainbowified = this.rainbowify(segment); - - for (var index = 0; index < this.numberOfLines; index++) { - var trajectory = this.trajectories[index]; - if (trajectory.length >= this.trajectoryWidthMax) trajectory.shift(); - trajectory.push(rainbowified); - } -}; - -/** - * Draw the rainbow. - * - * @api private - */ - -NyanCat.prototype.drawRainbow = function(){ - var self = this; - - this.trajectories.forEach(function(line, index) { - write('\u001b[' + self.scoreboardWidth + 'C'); - write(line.join('')); - write('\n'); - }); - - this.cursorUp(this.numberOfLines); -}; - -/** - * Draw the nyan cat with `status`. - * - * @param {String} status - * @api private - */ - -NyanCat.prototype.drawNyanCat = function(status) { - var self = this; - var startWidth = this.scoreboardWidth + this.trajectories[0].length; - var color = '\u001b[' + startWidth + 'C'; - var padding = ''; - - write(color); - write('_,------,'); - write('\n'); - - write(color); - padding = self.tick ? ' ' : ' '; - write('_|' + padding + '/\\_/\\ '); - write('\n'); - - write(color); - padding = self.tick ? '_' : '__'; - var tail = self.tick ? '~' : '^'; - var face; - switch (status) { - case 'pass': - face = '( ^ .^)'; - break; - case 'fail': - face = '( o .o)'; - break; - default: - face = '( - .-)'; - } - write(tail + '|' + padding + face + ' '); - write('\n'); - - write(color); - padding = self.tick ? ' ' : ' '; - write(padding + '"" "" '); - write('\n'); - - this.cursorUp(this.numberOfLines); -}; - -/** - * Move cursor up `n`. - * - * @param {Number} n - * @api private - */ - -NyanCat.prototype.cursorUp = function(n) { - write('\u001b[' + n + 'A'); -}; - -/** - * Move cursor down `n`. - * - * @param {Number} n - * @api private - */ - -NyanCat.prototype.cursorDown = function(n) { - write('\u001b[' + n + 'B'); -}; - -/** - * Generate rainbow colors. - * - * @return {Array} - * @api private - */ - -NyanCat.prototype.generateColors = function(){ - var colors = []; - - for (var i = 0; i < (6 * 7); i++) { - var pi3 = Math.floor(Math.PI / 3); - var n = (i * (1.0 / 6)); - var r = Math.floor(3 * Math.sin(n) + 3); - var g = Math.floor(3 * Math.sin(n + 2 * pi3) + 3); - var b = Math.floor(3 * Math.sin(n + 4 * pi3) + 3); - colors.push(36 * r + 6 * g + b + 16); - } - - return colors; -}; - -/** - * Apply rainbow to the given `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -NyanCat.prototype.rainbowify = function(str){ - var color = this.rainbowColors[this.colorIndex % this.rainbowColors.length]; - this.colorIndex += 1; - return '\u001b[38;5;' + color + 'm' + str + '\u001b[0m'; -}; - -/** - * Stdout helper. - */ - -function write(string) { - process.stdout.write(string); -} - -/** - * Inherit from `Base.prototype`. - */ - -function F(){}; -F.prototype = Base.prototype; -NyanCat.prototype = new F; -NyanCat.prototype.constructor = NyanCat; - - -}); // module: reporters/nyan.js - -require.register("reporters/progress.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `Progress`. - */ - -exports = module.exports = Progress; - -/** - * General progress bar color. - */ - -Base.colors.progress = 90; - -/** - * Initialize a new `Progress` bar test reporter. - * - * @param {Runner} runner - * @param {Object} options - * @api public - */ - -function Progress(runner, options) { - Base.call(this, runner); - - var self = this - , options = options || {} - , stats = this.stats - , width = Base.window.width * .50 | 0 - , total = runner.total - , complete = 0 - , max = Math.max; - - // default chars - options.open = options.open || '['; - options.complete = options.complete || '▬'; - options.incomplete = options.incomplete || Base.symbols.dot; - options.close = options.close || ']'; - options.verbose = false; - - // tests started - runner.on('start', function(){ - console.log(); - cursor.hide(); - }); - - // tests complete - runner.on('test end', function(){ - complete++; - var incomplete = total - complete - , percent = complete / total - , n = width * percent | 0 - , i = width - n; - - cursor.CR(); - process.stdout.write('\u001b[J'); - process.stdout.write(color('progress', ' ' + options.open)); - process.stdout.write(Array(n).join(options.complete)); - process.stdout.write(Array(i).join(options.incomplete)); - process.stdout.write(color('progress', options.close)); - if (options.verbose) { - process.stdout.write(color('progress', ' ' + complete + ' of ' + total)); - } - }); - - // tests are complete, output some stats - // and the failures if any - runner.on('end', function(){ - cursor.show(); - console.log(); - self.epilogue(); - }); -} - -/** - * Inherit from `Base.prototype`. - */ - -function F(){}; -F.prototype = Base.prototype; -Progress.prototype = new F; -Progress.prototype.constructor = Progress; - - -}); // module: reporters/progress.js - -require.register("reporters/spec.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `Spec`. - */ - -exports = module.exports = Spec; - -/** - * Initialize a new `Spec` test reporter. - * - * @param {Runner} runner - * @api public - */ - -function Spec(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , indents = 0 - , n = 0; - - function indent() { - return Array(indents).join(' ') - } - - runner.on('start', function(){ - console.log(); - }); - - runner.on('suite', function(suite){ - ++indents; - console.log(color('suite', '%s%s'), indent(), suite.title); - }); - - runner.on('suite end', function(suite){ - --indents; - if (1 == indents) console.log(); - }); - - runner.on('test', function(test){ - process.stdout.write(indent() + color('pass', ' ◦ ' + test.title + ': ')); - }); - - runner.on('pending', function(test){ - var fmt = indent() + color('pending', ' - %s'); - console.log(fmt, test.title); - }); - - runner.on('pass', function(test){ - if ('fast' == test.speed) { - var fmt = indent() - + color('checkmark', ' ' + Base.symbols.ok) - + color('pass', ' %s '); - cursor.CR(); - console.log(fmt, test.title); - } else { - var fmt = indent() - + color('checkmark', ' ' + Base.symbols.ok) - + color('pass', ' %s ') - + color(test.speed, '(%dms)'); - cursor.CR(); - console.log(fmt, test.title, test.duration); - } - }); - - runner.on('fail', function(test, err){ - cursor.CR(); - console.log(indent() + color('fail', ' %d) %s'), ++n, test.title); - }); - - runner.on('end', self.epilogue.bind(self)); -} - -/** - * Inherit from `Base.prototype`. - */ - -function F(){}; -F.prototype = Base.prototype; -Spec.prototype = new F; -Spec.prototype.constructor = Spec; - - -}); // module: reporters/spec.js - -require.register("reporters/tap.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , cursor = Base.cursor - , color = Base.color; - -/** - * Expose `TAP`. - */ - -exports = module.exports = TAP; - -/** - * Initialize a new `TAP` reporter. - * - * @param {Runner} runner - * @api public - */ - -function TAP(runner) { - Base.call(this, runner); - - var self = this - , stats = this.stats - , n = 1 - , passes = 0 - , failures = 0; - - runner.on('start', function(){ - var total = runner.grepTotal(runner.suite); - console.log('%d..%d', 1, total); - }); - - runner.on('test end', function(){ - ++n; - }); - - runner.on('pending', function(test){ - console.log('ok %d %s # SKIP -', n, title(test)); - }); - - runner.on('pass', function(test){ - passes++; - console.log('ok %d %s', n, title(test)); - }); - - runner.on('fail', function(test, err){ - failures++; - console.log('not ok %d %s', n, title(test)); - if (err.stack) console.log(err.stack.replace(/^/gm, ' ')); - }); - - runner.on('end', function(){ - console.log('# tests ' + (passes + failures)); - console.log('# pass ' + passes); - console.log('# fail ' + failures); - }); -} - -/** - * Return a TAP-safe title of `test` - * - * @param {Object} test - * @return {String} - * @api private - */ - -function title(test) { - return test.fullTitle().replace(/#/g, ''); -} - -}); // module: reporters/tap.js - -require.register("reporters/teamcity.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base'); - -/** - * Expose `Teamcity`. - */ - -exports = module.exports = Teamcity; - -/** - * Initialize a new `Teamcity` reporter. - * - * @param {Runner} runner - * @api public - */ - -function Teamcity(runner) { - Base.call(this, runner); - var stats = this.stats; - - runner.on('start', function() { - console.log("##teamcity[testSuiteStarted name='mocha.suite']"); - }); - - runner.on('test', function(test) { - console.log("##teamcity[testStarted name='" + escape(test.fullTitle()) + "']"); - }); - - runner.on('fail', function(test, err) { - console.log("##teamcity[testFailed name='" + escape(test.fullTitle()) + "' message='" + escape(err.message) + "']"); - }); - - runner.on('pending', function(test) { - console.log("##teamcity[testIgnored name='" + escape(test.fullTitle()) + "' message='pending']"); - }); - - runner.on('test end', function(test) { - console.log("##teamcity[testFinished name='" + escape(test.fullTitle()) + "' duration='" + test.duration + "']"); - }); - - runner.on('end', function() { - console.log("##teamcity[testSuiteFinished name='mocha.suite' duration='" + stats.duration + "']"); - }); -} - -/** - * Escape the given `str`. - */ - -function escape(str) { - return str - .replace(/\|/g, "||") - .replace(/\n/g, "|n") - .replace(/\r/g, "|r") - .replace(/\[/g, "|[") - .replace(/\]/g, "|]") - .replace(/\u0085/g, "|x") - .replace(/\u2028/g, "|l") - .replace(/\u2029/g, "|p") - .replace(/'/g, "|'"); -} - -}); // module: reporters/teamcity.js - -require.register("reporters/xunit.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Base = require('./base') - , utils = require('../utils') - , escape = utils.escape; - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date - , setTimeout = global.setTimeout - , setInterval = global.setInterval - , clearTimeout = global.clearTimeout - , clearInterval = global.clearInterval; - -/** - * Expose `XUnit`. - */ - -exports = module.exports = XUnit; - -/** - * Initialize a new `XUnit` reporter. - * - * @param {Runner} runner - * @api public - */ - -function XUnit(runner) { - Base.call(this, runner); - var stats = this.stats - , tests = [] - , self = this; - - runner.on('pass', function(test){ - tests.push(test); - }); - - runner.on('fail', function(test){ - tests.push(test); - }); - - runner.on('end', function(){ - console.log(tag('testsuite', { - name: 'Mocha Tests' - , tests: stats.tests - , failures: stats.failures - , errors: stats.failures - , skipped: stats.tests - stats.failures - stats.passes - , timestamp: (new Date).toUTCString() - , time: (stats.duration / 1000) || 0 - }, false)); - - tests.forEach(test); - console.log(''); - }); -} - -/** - * Inherit from `Base.prototype`. - */ - -function F(){}; -F.prototype = Base.prototype; -XUnit.prototype = new F; -XUnit.prototype.constructor = XUnit; - - -/** - * Output tag for the given `test.` - */ - -function test(test) { - var attrs = { - classname: test.parent.fullTitle() - , name: test.title - , time: test.duration / 1000 - }; - - if ('failed' == test.state) { - var err = test.err; - attrs.message = escape(err.message); - console.log(tag('testcase', attrs, false, tag('failure', attrs, false, cdata(err.stack)))); - } else if (test.pending) { - console.log(tag('testcase', attrs, false, tag('skipped', {}, true))); - } else { - console.log(tag('testcase', attrs, true) ); - } -} - -/** - * HTML tag helper. - */ - -function tag(name, attrs, close, content) { - var end = close ? '/>' : '>' - , pairs = [] - , tag; - - for (var key in attrs) { - pairs.push(key + '="' + escape(attrs[key]) + '"'); - } - - tag = '<' + name + (pairs.length ? ' ' + pairs.join(' ') : '') + end; - if (content) tag += content + ''; -} - -}); // module: reporters/xunit.js - -require.register("runnable.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('mocha:runnable') - , milliseconds = require('./ms'); - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date - , setTimeout = global.setTimeout - , setInterval = global.setInterval - , clearTimeout = global.clearTimeout - , clearInterval = global.clearInterval; - -/** - * Object#toString(). - */ - -var toString = Object.prototype.toString; - -/** - * Expose `Runnable`. - */ - -module.exports = Runnable; - -/** - * Initialize a new `Runnable` with the given `title` and callback `fn`. - * - * @param {String} title - * @param {Function} fn - * @api private - */ - -function Runnable(title, fn) { - this.title = title; - this.fn = fn; - this.async = fn && fn.length; - this.sync = ! this.async; - this._timeout = 2000; - this._slow = 75; - this.timedOut = false; -} - -/** - * Inherit from `EventEmitter.prototype`. - */ - -function F(){}; -F.prototype = EventEmitter.prototype; -Runnable.prototype = new F; -Runnable.prototype.constructor = Runnable; - - -/** - * Set & get timeout `ms`. - * - * @param {Number|String} ms - * @return {Runnable|Number} ms or self - * @api private - */ - -Runnable.prototype.timeout = function(ms){ - if (0 == arguments.length) return this._timeout; - if ('string' == typeof ms) ms = milliseconds(ms); - debug('timeout %d', ms); - this._timeout = ms; - if (this.timer) this.resetTimeout(); - return this; -}; - -/** - * Set & get slow `ms`. - * - * @param {Number|String} ms - * @return {Runnable|Number} ms or self - * @api private - */ - -Runnable.prototype.slow = function(ms){ - if (0 === arguments.length) return this._slow; - if ('string' == typeof ms) ms = milliseconds(ms); - debug('timeout %d', ms); - this._slow = ms; - return this; -}; - -/** - * Return the full title generated by recursively - * concatenating the parent's full title. - * - * @return {String} - * @api public - */ - -Runnable.prototype.fullTitle = function(){ - return this.parent.fullTitle() + ' ' + this.title; -}; - -/** - * Clear the timeout. - * - * @api private - */ - -Runnable.prototype.clearTimeout = function(){ - clearTimeout(this.timer); -}; - -/** - * Inspect the runnable void of private properties. - * - * @return {String} - * @api private - */ - -Runnable.prototype.inspect = function(){ - return JSON.stringify(this, function(key, val){ - if ('_' == key[0]) return; - if ('parent' == key) return '#'; - if ('ctx' == key) return '#'; - return val; - }, 2); -}; - -/** - * Reset the timeout. - * - * @api private - */ - -Runnable.prototype.resetTimeout = function(){ - var self = this; - var ms = this.timeout() || 1e9; - - this.clearTimeout(); - this.timer = setTimeout(function(){ - self.callback(new Error('timeout of ' + ms + 'ms exceeded')); - self.timedOut = true; - }, ms); -}; - -/** - * Run the test and invoke `fn(err)`. - * - * @param {Function} fn - * @api private - */ - -Runnable.prototype.run = function(fn){ - var self = this - , ms = this.timeout() - , start = new Date - , ctx = this.ctx - , finished - , emitted; - - if (ctx) ctx.runnable(this); - - // timeout - if (this.async) { - if (ms) { - this.timer = setTimeout(function(){ - done(new Error('timeout of ' + ms + 'ms exceeded')); - self.timedOut = true; - }, ms); - } - } - - // called multiple times - function multiple(err) { - if (emitted) return; - emitted = true; - self.emit('error', err || new Error('done() called multiple times')); - } - - // finished - function done(err) { - if (self.timedOut) return; - if (finished) return multiple(err); - self.clearTimeout(); - self.duration = new Date - start; - finished = true; - fn(err); - } - - // for .resetTimeout() - this.callback = done; - - // async - if (this.async) { - try { - this.fn.call(ctx, function(err){ - if (err instanceof Error || toString.call(err) === "[object Error]") return done(err); - if (null != err) return done(new Error('done() invoked with non-Error: ' + err)); - done(); - }); - } catch (err) { - done(err); - } - return; - } - - if (this.asyncOnly) { - return done(new Error('--async-only option in use without declaring `done()`')); - } - - // sync - try { - if (!this.pending) this.fn.call(ctx); - this.duration = new Date - start; - fn(); - } catch (err) { - fn(err); - } -}; - -}); // module: runnable.js - -require.register("runner.js", function(module, exports, require){ -/** - * Module dependencies. - */ - -var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('mocha:runner') - , Test = require('./test') - , utils = require('./utils') - , filter = utils.filter - , keys = utils.keys; - -/** - * Non-enumerable globals. - */ - -var globals = [ - 'setTimeout', - 'clearTimeout', - 'setInterval', - 'clearInterval', - 'XMLHttpRequest', - 'Date' -]; - -/** - * Expose `Runner`. - */ - -module.exports = Runner; - -/** - * Initialize a `Runner` for the given `suite`. - * - * Events: - * - * - `start` execution started - * - `end` execution complete - * - `suite` (suite) test suite execution started - * - `suite end` (suite) all tests (and sub-suites) have finished - * - `test` (test) test execution started - * - `test end` (test) test completed - * - `hook` (hook) hook execution started - * - `hook end` (hook) hook complete - * - `pass` (test) test passed - * - `fail` (test, err) test failed - * - `pending` (test) test pending - * - * @api public - */ - -function Runner(suite) { - var self = this; - this._globals = []; - this.suite = suite; - this.total = suite.total(); - this.failures = 0; - this.on('test end', function(test){ self.checkGlobals(test); }); - this.on('hook end', function(hook){ self.checkGlobals(hook); }); - this.grep(/.*/); - this.globals(this.globalProps().concat(['errno'])); -} - -/** - * Wrapper for setImmediate, process.nextTick, or browser polyfill. - * - * @param {Function} fn - * @api private - */ - -Runner.immediately = global.setImmediate || process.nextTick; - -/** - * Inherit from `EventEmitter.prototype`. - */ - -function F(){}; -F.prototype = EventEmitter.prototype; -Runner.prototype = new F; -Runner.prototype.constructor = Runner; - - -/** - * Run tests with full titles matching `re`. Updates runner.total - * with number of tests matched. - * - * @param {RegExp} re - * @param {Boolean} invert - * @return {Runner} for chaining - * @api public - */ - -Runner.prototype.grep = function(re, invert){ - debug('grep %s', re); - this._grep = re; - this._invert = invert; - this.total = this.grepTotal(this.suite); - return this; -}; - -/** - * Returns the number of tests matching the grep search for the - * given suite. - * - * @param {Suite} suite - * @return {Number} - * @api public - */ - -Runner.prototype.grepTotal = function(suite) { - var self = this; - var total = 0; - - suite.eachTest(function(test){ - var match = self._grep.test(test.fullTitle()); - if (self._invert) match = !match; - if (match) total++; - }); - - return total; -}; - -/** - * Return a list of global properties. - * - * @return {Array} - * @api private - */ - -Runner.prototype.globalProps = function() { - var props = utils.keys(global); - - // non-enumerables - for (var i = 0; i < globals.length; ++i) { - if (~utils.indexOf(props, globals[i])) continue; - props.push(globals[i]); - } - - return props; -}; - -/** - * Allow the given `arr` of globals. - * - * @param {Array} arr - * @return {Runner} for chaining - * @api public - */ - -Runner.prototype.globals = function(arr){ - if (0 == arguments.length) return this._globals; - debug('globals %j', arr); - utils.forEach(arr, function(arr){ - this._globals.push(arr); - }, this); - return this; -}; - -/** - * Check for global variable leaks. - * - * @api private - */ - -Runner.prototype.checkGlobals = function(test){ - if (this.ignoreLeaks) return; - var ok = this._globals; - var globals = this.globalProps(); - var isNode = process.kill; - var leaks; - - // check length - 2 ('errno' and 'location' globals) - if (isNode && 1 == ok.length - globals.length) return - else if (2 == ok.length - globals.length) return; - - leaks = filterLeaks(ok, globals); - this._globals = this._globals.concat(leaks); - - if (leaks.length > 1) { - this.fail(test, new Error('global leaks detected: ' + leaks.join(', ') + '')); - } else if (leaks.length) { - this.fail(test, new Error('global leak detected: ' + leaks[0])); - } -}; - -/** - * Fail the given `test`. - * - * @param {Test} test - * @param {Error} err - * @api private - */ - -Runner.prototype.fail = function(test, err){ - ++this.failures; - test.state = 'failed'; - - if ('string' == typeof err) { - err = new Error('the string "' + err + '" was thrown, throw an Error :)'); - } - - this.emit('fail', test, err); -}; - -/** - * Fail the given `hook` with `err`. - * - * Hook failures (currently) hard-end due - * to that fact that a failing hook will - * surely cause subsequent tests to fail, - * causing jumbled reporting. - * - * @param {Hook} hook - * @param {Error} err - * @api private - */ - -Runner.prototype.failHook = function(hook, err){ - this.fail(hook, err); - this.emit('end'); -}; - -/** - * Run hook `name` callbacks and then invoke `fn()`. - * - * @param {String} name - * @param {Function} function - * @api private - */ - -Runner.prototype.hook = function(name, fn){ - var suite = this.suite - , hooks = suite['_' + name] - , self = this - , timer; - - function next(i) { - var hook = hooks[i]; - if (!hook) return fn(); - if (self.failures && suite.bail()) return fn(); - self.currentRunnable = hook; - - hook.ctx.currentTest = self.test; - - self.emit('hook', hook); - - hook.on('error', function(err){ - self.failHook(hook, err); - }); - - hook.run(function(err){ - hook.removeAllListeners('error'); - var testError = hook.error(); - if (testError) self.fail(self.test, testError); - if (err) return self.failHook(hook, err); - self.emit('hook end', hook); - delete hook.ctx.currentTest; - next(++i); - }); - } - - Runner.immediately(function(){ - next(0); - }); -}; - -/** - * Run hook `name` for the given array of `suites` - * in order, and callback `fn(err)`. - * - * @param {String} name - * @param {Array} suites - * @param {Function} fn - * @api private - */ - -Runner.prototype.hooks = function(name, suites, fn){ - var self = this - , orig = this.suite; - - function next(suite) { - self.suite = suite; - - if (!suite) { - self.suite = orig; - return fn(); - } - - self.hook(name, function(err){ - if (err) { - self.suite = orig; - return fn(err); - } - - next(suites.pop()); - }); - } - - next(suites.pop()); -}; - -/** - * Run hooks from the top level down. - * - * @param {String} name - * @param {Function} fn - * @api private - */ - -Runner.prototype.hookUp = function(name, fn){ - var suites = [this.suite].concat(this.parents()).reverse(); - this.hooks(name, suites, fn); -}; - -/** - * Run hooks from the bottom up. - * - * @param {String} name - * @param {Function} fn - * @api private - */ - -Runner.prototype.hookDown = function(name, fn){ - var suites = [this.suite].concat(this.parents()); - this.hooks(name, suites, fn); -}; - -/** - * Return an array of parent Suites from - * closest to furthest. - * - * @return {Array} - * @api private - */ - -Runner.prototype.parents = function(){ - var suite = this.suite - , suites = []; - while (suite = suite.parent) suites.push(suite); - return suites; -}; - -/** - * Run the current test and callback `fn(err)`. - * - * @param {Function} fn - * @api private - */ - -Runner.prototype.runTest = function(fn){ - var test = this.test - , self = this; - - if (this.asyncOnly) test.asyncOnly = true; - - try { - test.on('error', function(err){ - self.fail(test, err); - }); - test.run(fn); - } catch (err) { - fn(err); - } -}; - -/** - * Run tests in the given `suite` and invoke - * the callback `fn()` when complete. - * - * @param {Suite} suite - * @param {Function} fn - * @api private - */ - -Runner.prototype.runTests = function(suite, fn){ - var self = this - , tests = suite.tests.slice() - , test; - - function next(err) { - // if we bail after first err - if (self.failures && suite._bail) return fn(); - - // next test - test = tests.shift(); - - // all done - if (!test) return fn(); - - // grep - var match = self._grep.test(test.fullTitle()); - if (self._invert) match = !match; - if (!match) return next(); - - // pending - if (test.pending) { - self.emit('pending', test); - self.emit('test end', test); - return next(); - } - - // execute test and hook(s) - self.emit('test', self.test = test); - self.hookDown('beforeEach', function(){ - self.currentRunnable = self.test; - self.runTest(function(err){ - test = self.test; - - if (err) { - self.fail(test, err); - self.emit('test end', test); - return self.hookUp('afterEach', next); - } - - test.state = 'passed'; - self.emit('pass', test); - self.emit('test end', test); - self.hookUp('afterEach', next); - }); - }); - } - - this.next = next; - next(); -}; - -/** - * Run the given `suite` and invoke the - * callback `fn()` when complete. - * - * @param {Suite} suite - * @param {Function} fn - * @api private - */ - -Runner.prototype.runSuite = function(suite, fn){ - var total = this.grepTotal(suite) - , self = this - , i = 0; - - debug('run suite %s', suite.fullTitle()); - - if (!total) return fn(); - - this.emit('suite', this.suite = suite); - - function next() { - var curr = suite.suites[i++]; - if (!curr) return done(); - self.runSuite(curr, next); - } - - function done() { - self.suite = suite; - self.hook('afterAll', function(){ - self.emit('suite end', suite); - fn(); - }); - } - - this.hook('beforeAll', function(){ - self.runTests(suite, next); - }); -}; - -/** - * Handle uncaught exceptions. - * - * @param {Error} err - * @api private - */ - -Runner.prototype.uncaught = function(err){ - debug('uncaught exception %s', err.message); - var runnable = this.currentRunnable; - if (!runnable || 'failed' == runnable.state) return; - runnable.clearTimeout(); - err.uncaught = true; - this.fail(runnable, err); - - // recover from test - if ('test' == runnable.type) { - this.emit('test end', runnable); - this.hookUp('afterEach', this.next); - return; - } - - // bail on hooks - this.emit('end'); -}; - -/** - * Run the root suite and invoke `fn(failures)` - * on completion. - * - * @param {Function} fn - * @return {Runner} for chaining - * @api public - */ - -Runner.prototype.run = function(fn){ - var self = this - , fn = fn || function(){}; - - function uncaught(err){ - self.uncaught(err); - } - - debug('start'); - - // callback - this.on('end', function(){ - debug('end'); - process.removeListener('uncaughtException', uncaught); - fn(self.failures); - }); - - // run suites - this.emit('start'); - this.runSuite(this.suite, function(){ - debug('finished running'); - self.emit('end'); - }); - - // uncaught exception - process.on('uncaughtException', uncaught); - - return this; -}; - -/** - * Filter leaks with the given globals flagged as `ok`. - * - * @param {Array} ok - * @param {Array} globals - * @return {Array} - * @api private - */ - -function filterLeaks(ok, globals) { - return filter(globals, function(key){ - // Firefox and Chrome exposes iframes as index inside the window object - if (/^d+/.test(key)) return false; - var matched = filter(ok, function(ok){ - if (~ok.indexOf('*')) return 0 == key.indexOf(ok.split('*')[0]); - // Opera and IE expose global variables for HTML element IDs (issue #243) - if (/^mocha-/.test(key)) return true; - return key == ok; - }); - return matched.length == 0 && (!global.navigator || 'onerror' !== key); - }); -} - -}); // module: runner.js - -require.register("suite.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var EventEmitter = require('browser/events').EventEmitter - , debug = require('browser/debug')('mocha:suite') - , milliseconds = require('./ms') - , utils = require('./utils') - , Hook = require('./hook'); - -/** - * Expose `Suite`. - */ - -exports = module.exports = Suite; - -/** - * Create a new `Suite` with the given `title` - * and parent `Suite`. When a suite with the - * same title is already present, that suite - * is returned to provide nicer reporter - * and more flexible meta-testing. - * - * @param {Suite} parent - * @param {String} title - * @return {Suite} - * @api public - */ - -exports.create = function(parent, title){ - var suite = new Suite(title, parent.ctx); - suite.parent = parent; - if (parent.pending) suite.pending = true; - title = suite.fullTitle(); - parent.addSuite(suite); - return suite; -}; - -/** - * Initialize a new `Suite` with the given - * `title` and `ctx`. - * - * @param {String} title - * @param {Context} ctx - * @api private - */ - -function Suite(title, ctx) { - this.title = title; - this.ctx = ctx; - this.suites = []; - this.tests = []; - this.pending = false; - this._beforeEach = []; - this._beforeAll = []; - this._afterEach = []; - this._afterAll = []; - this.root = !title; - this._timeout = 2000; - this._slow = 75; - this._bail = false; -} - -/** - * Inherit from `EventEmitter.prototype`. - */ - -function F(){}; -F.prototype = EventEmitter.prototype; -Suite.prototype = new F; -Suite.prototype.constructor = Suite; - - -/** - * Return a clone of this `Suite`. - * - * @return {Suite} - * @api private - */ - -Suite.prototype.clone = function(){ - var suite = new Suite(this.title); - debug('clone'); - suite.ctx = this.ctx; - suite.timeout(this.timeout()); - suite.slow(this.slow()); - suite.bail(this.bail()); - return suite; -}; - -/** - * Set timeout `ms` or short-hand such as "2s". - * - * @param {Number|String} ms - * @return {Suite|Number} for chaining - * @api private - */ - -Suite.prototype.timeout = function(ms){ - if (0 == arguments.length) return this._timeout; - if ('string' == typeof ms) ms = milliseconds(ms); - debug('timeout %d', ms); - this._timeout = parseInt(ms, 10); - return this; -}; - -/** - * Set slow `ms` or short-hand such as "2s". - * - * @param {Number|String} ms - * @return {Suite|Number} for chaining - * @api private - */ - -Suite.prototype.slow = function(ms){ - if (0 === arguments.length) return this._slow; - if ('string' == typeof ms) ms = milliseconds(ms); - debug('slow %d', ms); - this._slow = ms; - return this; -}; - -/** - * Sets whether to bail after first error. - * - * @parma {Boolean} bail - * @return {Suite|Number} for chaining - * @api private - */ - -Suite.prototype.bail = function(bail){ - if (0 == arguments.length) return this._bail; - debug('bail %s', bail); - this._bail = bail; - return this; -}; - -/** - * Run `fn(test[, done])` before running tests. - * - * @param {Function} fn - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.beforeAll = function(fn){ - if (this.pending) return this; - var hook = new Hook('"before all" hook', fn); - hook.parent = this; - hook.timeout(this.timeout()); - hook.slow(this.slow()); - hook.ctx = this.ctx; - this._beforeAll.push(hook); - this.emit('beforeAll', hook); - return this; -}; - -/** - * Run `fn(test[, done])` after running tests. - * - * @param {Function} fn - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.afterAll = function(fn){ - if (this.pending) return this; - var hook = new Hook('"after all" hook', fn); - hook.parent = this; - hook.timeout(this.timeout()); - hook.slow(this.slow()); - hook.ctx = this.ctx; - this._afterAll.push(hook); - this.emit('afterAll', hook); - return this; -}; - -/** - * Run `fn(test[, done])` before each test case. - * - * @param {Function} fn - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.beforeEach = function(fn){ - if (this.pending) return this; - var hook = new Hook('"before each" hook', fn); - hook.parent = this; - hook.timeout(this.timeout()); - hook.slow(this.slow()); - hook.ctx = this.ctx; - this._beforeEach.push(hook); - this.emit('beforeEach', hook); - return this; -}; - -/** - * Run `fn(test[, done])` after each test case. - * - * @param {Function} fn - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.afterEach = function(fn){ - if (this.pending) return this; - var hook = new Hook('"after each" hook', fn); - hook.parent = this; - hook.timeout(this.timeout()); - hook.slow(this.slow()); - hook.ctx = this.ctx; - this._afterEach.push(hook); - this.emit('afterEach', hook); - return this; -}; - -/** - * Add a test `suite`. - * - * @param {Suite} suite - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.addSuite = function(suite){ - suite.parent = this; - suite.timeout(this.timeout()); - suite.slow(this.slow()); - suite.bail(this.bail()); - this.suites.push(suite); - this.emit('suite', suite); - return this; -}; - -/** - * Add a `test` to this suite. - * - * @param {Test} test - * @return {Suite} for chaining - * @api private - */ - -Suite.prototype.addTest = function(test){ - test.parent = this; - test.timeout(this.timeout()); - test.slow(this.slow()); - test.ctx = this.ctx; - this.tests.push(test); - this.emit('test', test); - return this; -}; - -/** - * Return the full title generated by recursively - * concatenating the parent's full title. - * - * @return {String} - * @api public - */ - -Suite.prototype.fullTitle = function(){ - if (this.parent) { - var full = this.parent.fullTitle(); - if (full) return full + ' ' + this.title; - } - return this.title; -}; - -/** - * Return the total number of tests. - * - * @return {Number} - * @api public - */ - -Suite.prototype.total = function(){ - return utils.reduce(this.suites, function(sum, suite){ - return sum + suite.total(); - }, 0) + this.tests.length; -}; - -/** - * Iterates through each suite recursively to find - * all tests. Applies a function in the format - * `fn(test)`. - * - * @param {Function} fn - * @return {Suite} - * @api private - */ - -Suite.prototype.eachTest = function(fn){ - utils.forEach(this.tests, fn); - utils.forEach(this.suites, function(suite){ - suite.eachTest(fn); - }); - return this; -}; - -}); // module: suite.js - -require.register("test.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var Runnable = require('./runnable'); - -/** - * Expose `Test`. - */ - -module.exports = Test; - -/** - * Initialize a new `Test` with the given `title` and callback `fn`. - * - * @param {String} title - * @param {Function} fn - * @api private - */ - -function Test(title, fn) { - Runnable.call(this, title, fn); - this.pending = !fn; - this.type = 'test'; -} - -/** - * Inherit from `Runnable.prototype`. - */ - -function F(){}; -F.prototype = Runnable.prototype; -Test.prototype = new F; -Test.prototype.constructor = Test; - - -}); // module: test.js - -require.register("utils.js", function(module, exports, require){ - -/** - * Module dependencies. - */ - -var fs = require('browser/fs') - , path = require('browser/path') - , join = path.join - , debug = require('browser/debug')('mocha:watch'); - -/** - * Ignored directories. - */ - -var ignore = ['node_modules', '.git']; - -/** - * Escape special characters in the given string of html. - * - * @param {String} html - * @return {String} - * @api private - */ - -exports.escape = function(html){ - return String(html) - .replace(/&/g, '&') - .replace(/"/g, '"') - .replace(//g, '>'); -}; - -/** - * Array#forEach (<=IE8) - * - * @param {Array} array - * @param {Function} fn - * @param {Object} scope - * @api private - */ - -exports.forEach = function(arr, fn, scope){ - for (var i = 0, l = arr.length; i < l; i++) - fn.call(scope, arr[i], i); -}; - -/** - * Array#indexOf (<=IE8) - * - * @parma {Array} arr - * @param {Object} obj to find index of - * @param {Number} start - * @api private - */ - -exports.indexOf = function(arr, obj, start){ - for (var i = start || 0, l = arr.length; i < l; i++) { - if (arr[i] === obj) - return i; - } - return -1; -}; - -/** - * Array#reduce (<=IE8) - * - * @param {Array} array - * @param {Function} fn - * @param {Object} initial value - * @api private - */ - -exports.reduce = function(arr, fn, val){ - var rval = val; - - for (var i = 0, l = arr.length; i < l; i++) { - rval = fn(rval, arr[i], i, arr); - } - - return rval; -}; - -/** - * Array#filter (<=IE8) - * - * @param {Array} array - * @param {Function} fn - * @api private - */ - -exports.filter = function(arr, fn){ - var ret = []; - - for (var i = 0, l = arr.length; i < l; i++) { - var val = arr[i]; - if (fn(val, i, arr)) ret.push(val); - } - - return ret; -}; - -/** - * Object.keys (<=IE8) - * - * @param {Object} obj - * @return {Array} keys - * @api private - */ - -exports.keys = Object.keys || function(obj) { - var keys = [] - , has = Object.prototype.hasOwnProperty // for `window` on <=IE8 - - for (var key in obj) { - if (has.call(obj, key)) { - keys.push(key); - } - } - - return keys; -}; - -/** - * Watch the given `files` for changes - * and invoke `fn(file)` on modification. - * - * @param {Array} files - * @param {Function} fn - * @api private - */ - -exports.watch = function(files, fn){ - var options = { interval: 100 }; - files.forEach(function(file){ - debug('file %s', file); - fs.watchFile(file, options, function(curr, prev){ - if (prev.mtime < curr.mtime) fn(file); - }); - }); -}; - -/** - * Ignored files. - */ - -function ignored(path){ - return !~ignore.indexOf(path); -} - -/** - * Lookup files in the given `dir`. - * - * @return {Array} - * @api private - */ - -exports.files = function(dir, ret){ - ret = ret || []; - - fs.readdirSync(dir) - .filter(ignored) - .forEach(function(path){ - path = join(dir, path); - if (fs.statSync(path).isDirectory()) { - exports.files(path, ret); - } else if (path.match(/\.(js|coffee)$/)) { - ret.push(path); - } - }); - - return ret; -}; - -/** - * Compute a slug from the given `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -exports.slug = function(str){ - return str - .toLowerCase() - .replace(/ +/g, '-') - .replace(/[^-\w]/g, ''); -}; - -/** - * Strip the function definition from `str`, - * and re-indent for pre whitespace. - */ - -exports.clean = function(str) { - str = str - .replace(/^function *\(.*\) *{/, '') - .replace(/\s+\}$/, ''); - - var whitespace = str.match(/^\n?(\s*)/)[1] - , re = new RegExp('^' + whitespace, 'gm'); - - str = str.replace(re, ''); - - return exports.trim(str); -}; - -/** - * Escape regular expression characters in `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -exports.escapeRegexp = function(str){ - return str.replace(/[-\\^$*+?.()|[\]{}]/g, "\\$&"); -}; - -/** - * Trim the given `str`. - * - * @param {String} str - * @return {String} - * @api private - */ - -exports.trim = function(str){ - return str.replace(/^\s+|\s+$/g, ''); -}; - -/** - * Parse the given `qs`. - * - * @param {String} qs - * @return {Object} - * @api private - */ - -exports.parseQuery = function(qs){ - return exports.reduce(qs.replace('?', '').split('&'), function(obj, pair){ - var i = pair.indexOf('=') - , key = pair.slice(0, i) - , val = pair.slice(++i); - - obj[key] = decodeURIComponent(val); - return obj; - }, {}); -}; - -/** - * Highlight the given string of `js`. - * - * @param {String} js - * @return {String} - * @api private - */ - -function highlight(js) { - return js - .replace(//g, '>') - .replace(/\/\/(.*)/gm, '//$1') - .replace(/('.*?')/gm, '$1') - .replace(/(\d+\.\d+)/gm, '$1') - .replace(/(\d+)/gm, '$1') - .replace(/\bnew *(\w+)/gm, 'new $1') - .replace(/\b(function|new|throw|return|var|if|else)\b/gm, '$1') -} - -/** - * Highlight the contents of tag `name`. - * - * @param {String} name - * @api private - */ - -exports.highlightTags = function(name) { - var code = document.getElementsByTagName(name); - for (var i = 0, len = code.length; i < len; ++i) { - code[i].innerHTML = highlight(code[i].innerHTML); - } -}; - -}); // module: utils.js -// The global object is "self" in Web Workers. -global = (function() { return this; })(); - -/** - * Save timer references to avoid Sinon interfering (see GH-237). - */ - -var Date = global.Date; -var setTimeout = global.setTimeout; -var setInterval = global.setInterval; -var clearTimeout = global.clearTimeout; -var clearInterval = global.clearInterval; - -/** - * Node shims. - * - * These are meant only to allow - * mocha.js to run untouched, not - * to allow running node code in - * the browser. - */ - -var process = {}; -process.exit = function(status){}; -process.stdout = {}; - -/** - * Remove uncaughtException listener. - */ - -process.removeListener = function(e){ - if ('uncaughtException' == e) { - global.onerror = function() {}; - } -}; - -/** - * Implements uncaughtException listener. - */ - -process.on = function(e, fn){ - if ('uncaughtException' == e) { - global.onerror = function(err, url, line){ - fn(new Error(err + ' (' + url + ':' + line + ')')); - }; - } -}; - -/** - * Expose mocha. - */ - -var Mocha = global.Mocha = require('mocha'), - mocha = global.mocha = new Mocha({ reporter: 'html' }); - -var immediateQueue = [] - , immediateTimeout; - -function timeslice() { - var immediateStart = new Date().getTime(); - while (immediateQueue.length && (new Date().getTime() - immediateStart) < 100) { - immediateQueue.shift()(); - } - if (immediateQueue.length) { - immediateTimeout = setTimeout(timeslice, 0); - } else { - immediateTimeout = null; - } -} - -/** - * High-performance override of Runner.immediately. - */ - -Mocha.Runner.immediately = function(callback) { - immediateQueue.push(callback); - if (!immediateTimeout) { - immediateTimeout = setTimeout(timeslice, 0); - } -}; - -/** - * Override ui to ensure that the ui functions are initialized. - * Normally this would happen in Mocha.prototype.loadFiles. - */ - -mocha.ui = function(ui){ - Mocha.prototype.ui.call(this, ui); - this.suite.emit('pre-require', global, null, this); - return this; -}; - -/** - * Setup mocha with the given setting options. - */ - -mocha.setup = function(opts){ - if ('string' == typeof opts) opts = { ui: opts }; - for (var opt in opts) this[opt](opts[opt]); - return this; -}; - -/** - * Run mocha, returning the Runner. - */ - -mocha.run = function(fn){ - var options = mocha.options; - mocha.globals('location'); - - var query = Mocha.utils.parseQuery(global.location.search || ''); - if (query.grep) mocha.grep(query.grep); - if (query.invert) mocha.invert(); - - return Mocha.prototype.run.call(mocha, function(){ - // The DOM Document is not available in Web Workers. - if (global.document) { - Mocha.utils.highlightTags('code'); - } - if (fn) fn(); - }); -}; - -/** - * Expose the process shim. - */ - -Mocha.process = process; -})(); \ No newline at end of file diff --git a/test/unit/static/js/proclaim.js b/test/unit/static/js/proclaim.js deleted file mode 100644 index 8ec76cee2..000000000 --- a/test/unit/static/js/proclaim.js +++ /dev/null @@ -1,528 +0,0 @@ -/* global define */ -(function (root) { - 'use strict'; - - // NOTE: One change has been made from stock proclaim.js: it now - // explicitly puts the fallback message (which had previously only been - // included in AssertionError#toString) into the error's `message` - // property. Without this, a failed test would display `undefined` in - // Mocha unless it had its own message. -APD - - var proclaim = ok; - - // Assertions as outlined in - // http://wiki.commonjs.org/wiki/Unit_Testing/1.0#Assert - // ----------------------------------------------------- - - // Assert that a value is truthy - function ok (val, msg) { - if (!!!val) { - fail(val, true, msg, '=='); - } - } - proclaim.ok = ok; - - // Assert that two values are equal - proclaim.equal = function (actual, expected, msg) { - /* jshint eqeqeq: false */ - if (actual != expected) { - fail(actual, expected, msg, '=='); - } - }; - - // Assert that two values are not equal - proclaim.notEqual = function (actual, expected, msg) { - /* jshint eqeqeq: false */ - if (actual == expected) { - fail(actual, expected, msg, '!='); - } - }; - - // Assert that two values are equal with strict comparison - proclaim.strictEqual = function (actual, expected, msg) { - if (actual !== expected) { - fail(actual, expected, msg, '==='); - } - }; - - // Assert that two values are not equal with strict comparison - proclaim.notStrictEqual = function (actual, expected, msg) { - if (actual === expected) { - fail(actual, expected, msg, '!=='); - } - }; - - // Assert that two values are deeply equal - proclaim.deepEqual = function (actual, expected, msg) { - if (!isDeepEqual(actual, expected)) { - fail(actual, expected, msg, 'deepEqual'); - } - }; - - // Assert that two values are not deeply equal - proclaim.notDeepEqual = function (actual, expected, msg) { - if (isDeepEqual(actual, expected)) { - fail(actual, expected, msg, '!deepEqual'); - } - }; - - // Assert that a function throws an error - proclaim['throws'] = function (fn, expected, msg) { - if (!functionThrows(fn, expected)) { - fail(fn, expected, msg, 'throws'); - } - }; - - - // Additional assertions - // --------------------- - - // Assert that a value is falsy - proclaim.notOk = function (val, msg) { - if (!!val) { - fail(val, true, msg, '!='); - } - }; - - // Assert that a function does not throw an error - proclaim.doesNotThrow = function (fn, expected, msg) { - if (functionThrows(fn, expected)) { - fail(fn, expected, msg, '!throws'); - } - }; - - // Assert that a value is a specific type - proclaim.isTypeOf = function (val, type, msg) { - proclaim.strictEqual(typeof val, type, msg); - }; - - // Assert that a value is not a specific type - proclaim.isNotTypeOf = function (val, type, msg) { - proclaim.notStrictEqual(typeof val, type, msg); - }; - - // Assert that a value is an instance of a constructor - proclaim.isInstanceOf = function (val, constructor, msg) { - if (!(val instanceof constructor)) { - fail(val, constructor, msg, 'instanceof'); - } - }; - - // Assert that a value not an instance of a constructor - proclaim.isNotInstanceOf = function (val, constructor, msg) { - if (val instanceof constructor) { - fail(val, constructor, msg, '!instanceof'); - } - }; - - // Assert that a value is an array - proclaim.isArray = function (val, msg) { - if (!isArray(val)) { - fail(typeof val, 'array', msg, '==='); - } - }; - - // Assert that a value is not an array - proclaim.isNotArray = function (val, msg) { - if (isArray(val)) { - fail(typeof val, 'array', msg, '!=='); - } - }; - - // Assert that a value is a boolean - proclaim.isBoolean = function (val, msg) { - proclaim.isTypeOf(val, 'boolean', msg); - }; - - // Assert that a value is not a boolean - proclaim.isNotBoolean = function (val, msg) { - proclaim.isNotTypeOf(val, 'boolean', msg); - }; - - // Assert that a value is true - proclaim.isTrue = function (val, msg) { - proclaim.strictEqual(val, true, msg); - }; - - // Assert that a value is false - proclaim.isFalse = function (val, msg) { - proclaim.strictEqual(val, false, msg); - }; - - // Assert that a value is a function - proclaim.isFunction = function (val, msg) { - proclaim.isTypeOf(val, 'function', msg); - }; - - // Assert that a value is not a function - proclaim.isNotFunction = function (val, msg) { - proclaim.isNotTypeOf(val, 'function', msg); - }; - - // Assert that a value is null - proclaim.isNull = function (val, msg) { - proclaim.strictEqual(val, null, msg); - }; - - // Assert that a value is not null - proclaim.isNotNull = function (val, msg) { - proclaim.notStrictEqual(val, null, msg); - }; - - // Assert that a value is a number - proclaim.isNumber = function (val, msg) { - proclaim.isTypeOf(val, 'number', msg); - }; - - // Assert that a value is not a number - proclaim.isNotNumber = function (val, msg) { - proclaim.isNotTypeOf(val, 'number', msg); - }; - - // Assert that a value is an object - proclaim.isObject = function (val, msg) { - proclaim.isTypeOf(val, 'object', msg); - }; - - // Assert that a value is not an object - proclaim.isNotObject = function (val, msg) { - proclaim.isNotTypeOf(val, 'object', msg); - }; - - // Assert that a value is a string - proclaim.isString = function (val, msg) { - proclaim.isTypeOf(val, 'string', msg); - }; - - // Assert that a value is not a string - proclaim.isNotString = function (val, msg) { - proclaim.isNotTypeOf(val, 'string', msg); - }; - - // Assert that a value is undefined - proclaim.isUndefined = function (val, msg) { - proclaim.isTypeOf(val, 'undefined', msg); - }; - - // Assert that a value is defined - proclaim.isDefined = function (val, msg) { - proclaim.isNotTypeOf(val, 'undefined', msg); - }; - - // Assert that a value matches a regular expression - proclaim.match = function (actual, expected, msg) { - if (!expected.test(actual)) { - fail(actual, expected, msg, 'match'); - } - }; - - // Assert that a value does not match a regular expression - proclaim.notMatch = function (actual, expected, msg) { - if (expected.test(actual)) { - fail(actual, expected, msg, '!match'); - } - }; - - // Assert that an object includes something - proclaim.includes = function (haystack, needle, msg) { - if (!includes(haystack, needle)) { - fail(haystack, needle, msg, 'include'); - } - }; - - // Assert that an object does not include something - proclaim.doesNotInclude = function (haystack, needle, msg) { - if (includes(haystack, needle)) { - fail(haystack, needle, msg, '!include'); - } - }; - - // Assert that an object (Array, String, etc.) has the expected length - proclaim.lengthEquals = function (obj, expected, msg) { - var undef; - if (isUndefinedOrNull(obj)) { - return fail(undef, expected, msg, 'length'); - } - if (obj.length !== expected) { - fail(obj.length, expected, msg, 'length'); - } - }; - - // Assert that a value is less than another value - proclaim.lessThan = function (actual, expected, msg) { - if (actual >= expected) { - fail(actual, expected, msg, '<'); - } - }; - - // Assert that a value is less than or equal to another value - proclaim.lessThanOrEqual = function (actual, expected, msg) { - if (actual > expected) { - fail(actual, expected, msg, '<='); - } - }; - - // Assert that a value is greater than another value - proclaim.greaterThan = function (actual, expected, msg) { - if (actual <= expected) { - fail(actual, expected, msg, '>'); - } - }; - - // Assert that a value is greater than another value - proclaim.greaterThanOrEqual = function (actual, expected, msg) { - if (actual < expected) { - fail(actual, expected, msg, '>='); - } - }; - - - // Error handling - // -------------- - - // Assertion error class - function AssertionError (opts) { - opts = opts || {}; - this.name = 'AssertionError'; - this.actual = opts.actual; - this.expected = opts.expected; - this.operator = opts.operator || ''; - this._message = opts.message; - - this.message = this._describe(); - - if (Error.captureStackTrace) { - Error.captureStackTrace(this, opts.stackStartFunction || fail); - } - } - AssertionError.prototype = (Object.create ? Object.create(Error.prototype) : new Error()); - AssertionError.prototype.name = 'AssertionError'; - AssertionError.prototype.constructor = AssertionError; - - AssertionError.prototype._describe = function () { - var output = this.actual + ' ' + - this.operator + ' ' + - this.expected; - - return this._message ? this._message + ': ' + output : output; - }; - - // Assertion error to string - AssertionError.prototype.toString = function () { - return this.name + ': ' + this._describe(); - }; - - // Fail a test - function fail (actual, expected, message, operator, stackStartFunction) { - throw new AssertionError({ - message: message, - actual: actual, - expected: expected, - operator: operator, - stackStartFunction: stackStartFunction - }); - } - - // Expose error handling tools - proclaim.AssertionError = AssertionError; - proclaim.fail = fail; - - - // Utilities - // --------- - - // Utility for checking whether a value is undefined or null - function isUndefinedOrNull (val) { - return (val === null || typeof val === 'undefined'); - } - - // Utility for checking whether a value is an arguments object - function isArgumentsObject (val) { - return (Object.prototype.toString.call(val) === '[object Arguments]'); - } - - // Utility for checking whether a value is plain object - function isPlainObject (val) { - return Object.prototype.toString.call(val) === '[object Object]'; - } - - // Utility for checking whether an object contains another object - function includes (haystack, needle) { - /* jshint maxdepth: 3*/ - var i; - - // Array#indexOf, but ie... - if (isArray(haystack)) { - for (i = haystack.length - 1; i >= 0; i = i - 1) { - if (haystack[i] === needle) { - return true; - } - } - } - - // String#indexOf - if (typeof haystack === 'string') { - if (haystack.indexOf(needle) !== -1) { - return true; - } - } - - // Object#hasOwnProperty - if (isPlainObject(haystack)) { - if (haystack.hasOwnProperty(needle)) { - return true; - } - } - - return false; - } - - // Utility for checking whether a value is an array - var isArray = Array.isArray || function (val) { - return (Object.prototype.toString.call(val) === '[object Array]'); - }; - - // Utility for getting object keys - function getObjectKeys (obj) { - var key, keys = []; - for (key in obj) { - if (obj.hasOwnProperty(key)) { - keys.push(key); - } - } - return keys; - } - - // Utility for deep equality testing of objects - function objectsEqual (obj1, obj2) { - /* jshint eqeqeq: false */ - - // Check for undefined or null - if (isUndefinedOrNull(obj1) || isUndefinedOrNull(obj2)) { - return false; - } - - // Object prototypes must be the same - if (obj1.prototype !== obj2.prototype) { - return false; - } - - // Handle argument objects - if (isArgumentsObject(obj1)) { - if (!isArgumentsObject(obj2)) { - return false; - } - obj1 = Array.prototype.slice.call(obj1); - obj2 = Array.prototype.slice.call(obj2); - } - - // Check number of own properties - var obj1Keys = getObjectKeys(obj1); - var obj2Keys = getObjectKeys(obj2); - if (obj1Keys.length !== obj2Keys.length) { - return false; - } - - obj1Keys.sort(); - obj2Keys.sort(); - - // Cheap initial key test (see https://github.com/joyent/node/blob/master/lib/assert.js) - var key, i, len = obj1Keys.length; - for (i = 0; i < len; i += 1) { - if (obj1Keys[i] != obj2Keys[i]) { - return false; - } - } - - // Expensive deep test - for (i = 0; i < len; i += 1) { - key = obj1Keys[i]; - if (!isDeepEqual(obj1[key], obj2[key])) { - return false; - } - } - - // If it got this far... - return true; - } - - // Utility for deep equality testing - function isDeepEqual (actual, expected) { - /* jshint eqeqeq: false */ - if (actual === expected) { - return true; - } - if (expected instanceof Date && actual instanceof Date) { - return actual.getTime() === expected.getTime(); - } - if (actual instanceof RegExp && expected instanceof RegExp) { - return ( - actual.source === expected.source && - actual.global === expected.global && - actual.multiline === expected.multiline && - actual.lastIndex === expected.lastIndex && - actual.ignoreCase === expected.ignoreCase - ); - } - if (typeof actual !== 'object' && typeof expected !== 'object') { - return actual == expected; - } - return objectsEqual(actual, expected); - } - - // Utility for testing whether a function throws an error - function functionThrows (fn, expected) { - - // Try/catch - var thrown = false; - var thrownError; - try { - fn(); - } catch (err) { - thrown = true; - thrownError = err; - } - - // Check error - if (thrown && expected) { - thrown = errorMatches(thrownError, expected); - } - - return thrown; - } - - // Utility for checking whether an error matches a given constructor, regexp or string - function errorMatches (actual, expected) { - if (typeof expected === 'string') { - return actual.message === expected; - } - if (expected instanceof RegExp) { - return expected.test(actual.message); - } - if (actual instanceof expected) { - return true; - } - return false; - } - - - // Exports - // ------- - - // AMD - if (typeof define !== 'undefined' && define.amd) { - define([], function () { - return proclaim; - }); - } - // CommonJS - else if (typeof module !== 'undefined' && module.exports) { - module.exports = proclaim; - } - // Script tag - else { - root.proclaim = proclaim; - } - - -} (this)); \ No newline at end of file diff --git a/test/unit/static/js/test_helpers.js b/test/unit/static/js/test_helpers.js deleted file mode 100644 index 01b8acb80..000000000 --- a/test/unit/static/js/test_helpers.js +++ /dev/null @@ -1,361 +0,0 @@ -// TODO: Ideally, none of the stuff in this file should use Prototype, so -// that a broken method inside Prototype does not end up affecting the test -// reporting. - -(function () { - // Needed because Mocha's HTML test runner assumes the presence of - // String#trim. - if (!String.prototype.trim) { - String.prototype.trim = String.prototype.strip; - } - - var CONSOLE_LOG_SUPPORTED = ('console' in window) && console.log; - var CONSOLE_GROUP_SUPPORTED = ('console' in window) && console.group && - console.groupEnd; - var CONSOLE_LOG_APPLY = true; - - // TODO: Find a different way to log info in IE9. - function info() { - if (CONSOLE_LOG_APPLY) { - console.log.apply(console, arguments); - } else { - console.log(arguments); - } - } - - function info_IE9() { - var log = $('log'); - log.show(); - var results = []; - for (var i = 0, len = arguments.length; i < len; i++) { - results.push(arguments[i].toString()); - } - var html = results.join(' '); - var p = new Element('p', { 'class': 'log-item' }); - p.update(html); - - log.insert(p); - // Force the log to scroll to the bottom whenever new stuff happens. - log.scrollTop = log.offsetHeight; - } - - if (!CONSOLE_LOG_SUPPORTED) { - info = info_IE9; - } else { - try { - console.log.apply(console, [""]); - } catch (e) { - CONSOLE_LOG_APPLY = false; - } - } - - window.info = info; - - // A function that acts like setTimeout, except with arguments reversed. This - // is far more readable within tests. - function wait(duration, done, fn) { - var handler = function () { - try { - fn(); - } catch (e) { - // Instead of relying on window.onerror to detect an error was - // thrown (which is problematic in IE6-7), we invoke the callback - // with an error the way Mocha expects. - return done(e); - } - }; - return setTimeout(handler, duration); - } - window.wait = wait; - - function buildMessage() { - var args = $A(arguments), message = args.shift(), template = args.shift(); - var output = template.interpolate(args.map(Object.inspect)); - return message ? (message + ': ' + output) : output; - } - - window.assert = proclaim; - - // Add our own assertions. - // - Object.extend(assert, { - enumEqual: function(expected, actual, message) { - expected = $A(expected); - actual = $A(actual); - - message = buildMessage( - message || 'assert.enumEqual', - 'expected collection #{0} to match collection #{1}', - actual, - expected - ); - - var passes = expected.length == actual.length && - expected.zip(actual).all(function(pair) { return pair[0] == pair[1]; }); - - if (!passes) { - assert.fail(actual, expected, message, 'enumEqual'); - } - }, - - identical: function (expected, actual, message) { - assert(expected === actual, message); - }, - - notIdentical: function (expected, actual, message) { - assert(expected !== actual, message); - }, - - enabled: function () { - for (var i = 0, element; element = arguments[i]; i++) { - assert( - !$(element).disabled, - 'element was disabled: ' + Object.inspect(element) - ); - } - }, - - disabled: function () { - for (var i = 0, element; element = arguments[i]; i++) { - assert( - $(element).disabled, - 'element was enabled: ' + Object.inspect(element) - ); - } - }, - - raise: function (exceptionName, fn, message) { - var raised = false; - try { - fn(); - } catch (e) { - if (e.name == exceptionName) - raised = true; - } - - assert(raised, message); - }, - - nothingRaised: function (fn, message) { - var raised = false; - try { - fn(); - } catch (e) { - raised = true; - } - - assert(!raised, message); - }, - - respondsTo: function (method, obj, message) { - message = (message || 'assertRespondsTo') + - ": object doesn't respond to <" + method + ">"; - var passes = (method in obj) && (typeof obj[method] === 'function'); - assert(passes, message); - }, - - elementsMatch: function () { - var message, passes = true, expressions = $A(arguments), elements = $A(expressions.shift()); - - if (elements.length !== expressions.length) { - passes = false; - message = 'Size mismatch: #{0} elements, #{1} expressions (#{2})'.interpolate( - [elements.length, expressions.length, expressions]); - } else { - elements.zip(expressions).all(function (pair, index) { - var element = $(pair.first()), expression = pair.last(); - if (element.match(expression)) return true; - - message = 'In index <#{0}>: expected <#{1}> but got #{2}'.interpolate( - [index, expression, Object.inspect(element)]); - passes = false; - }.bind(this)); - } - - assert(passes, message); - }, - - elementMatches: function (element, expression, message) { - this.elementsMatch([element], expression); - }, - - hashEqual: function (expected, actual, message) { - function assertPairEqual(pair) { - return pair.all(Object.isArray) ? - pair[0].zip(pair[1]).all(assertPairEqual) : pair[0] == pair[1]; - } - - expected = $H(expected); - actual = $H(actual); - - var eArray = expected.toArray().sort(); - var aArray = actual.toArray().sort(); - - var passes = (eArray.length === aArray.length) && - eArray.zip(aArray).all(assertPairEqual); - - assert(passes, message); - }, - - hashNotEqual: function (expected, actual, message) { - function assertPairEqual(pair) { - return pair.all(Object.isArray) ? - pair[0].zip(pair[1]).all(assertPairEqual) : pair[0] == pair[1]; - } - - expected = $H(expected); - actual = $H(actual); - - var eArray = expected.toArray().sort(); - var aArray = actual.toArray().sort(); - - var fails = (eArray.length === aArray.length) && - eArray.zip(aArray).all(assertPairEqual); - - assert(!fails, message); - }, - - isNotNullOrUndefined: function (val, message) { - if (val === null || typeof val === 'undefined') { - message = buildMessage( - message, - "expected #{0} not to be null/undefined", - val - ); - assert.fail(val, null, message, 'isNotNullOrUndefined'); - } - } - }); - - - // Add a bit of structure around the tests. - // - // All the tests run on the same page, but each test suite has its own HTML - // fixture. This makes it easy for them to get in each others' way. (The - // Selector tests, especially, are very particular about the types and - // quantities of elements on the page.) - // - // The way we manage this is to assemble all the HTML fixtures before any - // tests run, then detach them all from the document. Then, before a suite - // runs, its fixtures are reattached, then removed again before the next - // suite runs. - // - window.Test = { - setup: function () { - var body = document.body; - this.suites = body.getAttribute('data-suites').split(','); - - this.fixtures = {}; - - this.suites.each(function (suite) { - var fixtures = $('other_fixtures').down('[data-suite="' + suite + '"]'); - if (fixtures) { - this.fixtures[suite] = fixtures.remove();; - } - }, this); - }, - - startSuite: function (suite) { - if (CONSOLE_GROUP_SUPPORTED) { - console.group('Suite:', suite); - } else if (CONSOLE_LOG_SUPPORTED) { - console.log('Suite: ', suite); - } - - // Calling `remove` on this node has been known to crash the tests in - // IE6-7. - if (this.currentFixtures) { - document.getElementById('current_fixtures').innerHTML = ''; - } - - if (this.fixtures[suite]) { - this.currentFixtures = this.fixtures[suite]; - $('current_fixtures').insert(this.currentFixtures); - } - }, - - endSuite: function (suite) { - if (CONSOLE_GROUP_SUPPORTED) { - console.groupEnd(); - } - }, - - configureRunner: function (runner) { - var failedTests = []; - runner.on('end', function(){ - window.mochaResults = runner.stats; - window.mochaResults.reports = failedTests; - }); - - runner.on('fail', logFailure); - - function logFailure (test, err) { - function flattenTitles (test) { - var titles = []; - while (test.parent.title) { - titles.push(test.parent.title); - test = test.parent; - } - return titles.reverse(); - } - - failedTests.push({ - name: test.title, - result: false, - message: err.message, - stack: err.stack, - titles: flattenTitles(test) - }); - } - } - }; - - // Wrap Mocha's standard HTML reporter with some logic that pings a URL - // with a results summary once the tests are done. - var HTML = Mocha.reporters.HTML; - - // If there's a `results_url` parameter in the URL, we should use it. - var resultsUrl; - var queryParams = location.search.toQueryParams(); - - if (queryParams['results_url']) { - resultsUrl = queryParams['results_url']; - } - - Test.Reporter = function (runner, root) { - HTML.call(this, runner); - - runner.on('suite end', function (suite) { - if (!suite.root) { - return; - } - - $('mocha').addClassName('done'); - - if (!resultsUrl) { - return; - } - - var startMs = this.stats.start.valueOf(); - var endMs = (new Date).valueOf(); - var duration = (endMs - startMs) / 1000; - - var params = { - duration: duration, - tests: this.stats.tests, - passes: this.stats.passes, - failures: this.stats.failures - }; - - var url = resultsUrl + '?' + Object.toQueryString(params); - - var script = document.createElement('script'); - script.src = url; - document.body.appendChild(script); - setTimeout(function () { - document.body.removeChild(script); - }, 2000); - }); - }; - -})(); diff --git a/test/unit/tests/ajax.test.js b/test/unit/tests/ajax.test.js deleted file mode 100644 index de74074dd..000000000 --- a/test/unit/tests/ajax.test.js +++ /dev/null @@ -1,545 +0,0 @@ -Fixtures.Ajax = { - js: { - responseBody: '$("content").update("

      Hello world!

      ");', - 'Content-Type': ' text/javascript ' - }, - - html: { - responseBody: "Pack my box with five dozen liquor jugs! " + - "Oh, how quickly daft jumping zebras vex..." - }, - - xml: { - responseBody: 'bar', - 'Content-Type': 'application/xml' - }, - - json: { - responseBody: '{\n\r"test": 123}', - 'Content-Type': 'application/json' - }, - - jsonWithoutContentType: { - responseBody: '{"test": 123}' - }, - - invalidJson: { - responseBody: '{});window.attacked = true;({}', - 'Content-Type': 'application/json' - }, - - headerJson: { - 'X-JSON': '{"test": "hello #éà"}' - } -}; - -var responderCounter = 0; - -// lowercase comparison because of MSIE which presents HTML tags in uppercase -var sentence = ("Pack my box with five dozen liquor jugs! " + - "Oh, how quickly daft jumping zebras vex...").toLowerCase(); - -var message = 'You must be running a test server to test this feature.'; - -function assertContent(id, content, message) { - var a = content.toLowerCase(); - var b = $(id).innerHTML.strip().toLowerCase(); - message = message || 'failure'; - - assert.equal( - a, - b, - message + ': element #' + id + ' should have content: (' + a + ') but has content: (' + b + ')' - ); -} - - -var extendDefault = function(options) { - return Object.extend({ - asynchronous: false, - method: 'get' - }, options); -}; - -suite("Ajax", function () { - this.timeout(10000); - this.name = 'ajax'; - - setup(function () { - $('content', 'content2').invoke('update', ''); - }); - - teardown(function () { - // hack to cleanup responders - Ajax.Responders.responders = [Ajax.Responders.responders[0]]; - }); - - test("synchronous request", function () { - assert.equal("", $('content').innerHTML); - assert.equal(0, Ajax.activeRequestCount); - - new Ajax.Request('/fixtures/hello.js', { - asynchronous: false, - method: 'GET', - evalJS: 'force' - }); - - assert.equal(0, Ajax.activeRequestCount); - }); - - test("asynchronous request", function (done) { - assert.equal("", $("content").innerHTML); - - new Ajax.Request('/fixtures/hello.js', { - asynchronous: true, - method: 'GET', - evalJS: 'force' - }); - - setTimeout(function () { - var h2 = $('content').firstChild; - assert.equal("Hello world!", h2.innerHTML); - done(); - }, 1000); - }); - - test("activeRequestCount decrements when an exception occurs in a handler", function (done) { - - new Ajax.Request('/fixtures/hello.js', { - method: 'GET', - onComplete: function () { - assert.equal(1, Ajax.activeRequestCount); - setTimeout(function () { - assert.equal(0, Ajax.activeRequestCount); - done(); - }, 250); - throw new Error('test'); - }, - - onException: function () { - // Empty function to prevent the error from being rethrown - } - }); - - }); - - suite('Updater', function () { - - setup(function () { - $('content', 'content2').invoke('update', ''); - }); - - test('basic', function (done) { - assert.equal("", $('content').innerHTML); - - new Ajax.Updater('content', '/fixtures/content.html', { method: 'get' }); - - setTimeout(function () { - assertContent('content', sentence, 'simple updater'); - - $('content').update(''); - assert.equal("", $('content').innerHTML); - - new Ajax.Updater( - { success: 'content', failure: 'content2' }, - '/fixtures/content.html', - { method: 'get', parameters: { pet: 'monkey' } } - ); - - setTimeout(function () { - assertContent('content', sentence, 'success/failure updater'); - assertContent('content2', '', 'failure DIV should be empty'); - done(); - }, 1000); - - }, 1000); - - }); - - test('with insertion', function (done) { - $('content').update(); - new Ajax.Updater('content', '/fixtures/content.html', { - method: 'get', - insertion: Insertion.Top - }); - assertContent('content', ''); - - setTimeout(function() { - assertContent('content', sentence, 'Insertion.Top'); - $('content').update(); - - new Ajax.Updater('content', '/fixtures/content.html', { - method: 'get', - insertion: 'bottom' - }); - - setTimeout(function () { - assertContent('content', sentence, 'bottom insertion'); - $('content').update(); - - new Ajax.Updater('content', '/fixtures/content.html', { - method: 'get', - insertion: 'after' - }); - - setTimeout(function () { - assert.equal( - 'five dozen', - $('content').next().innerHTML.strip().toLowerCase(), - 'after insertion' - ); - done(); - }, 1000); - - }, 1000); - - }, 1000); - - }); - - test('with options', function () { - var options = { - method: 'get', - asynchronous: false, - evalJS: 'force', - onComplete: Prototype.emptyFunction - }; - - var request = new Ajax.Updater('content', '/fixtures/hello.js', options); - request.options.onComplete = Prototype.emptyFunction; - assert.strictEqual(Prototype.emptyFunction, options.onComplete); - }); - - }); // Updater - - test('responders', function (done) { - var r = Ajax.Responders.responders; - assert.equal(1, r.length); - - var dummyResponder = { - onComplete: Prototype.emptyFunction - }; - - Ajax.Responders.register(dummyResponder); - assert.equal(2, r.length); - - // Don't add twice. - Ajax.Responders.register(dummyResponder); - assert.equal(2, r.length, 'what'); - - Ajax.Responders.unregister(dummyResponder); - assert.equal(1, Ajax.Responders.responders.length); - - var responder = { - onCreate: function(req) { responderCounter++; }, - onLoading: function(req) { responderCounter++; }, - onComplete: function(req) { responderCounter++; } - }; - Ajax.Responders.register(responder); - - assert.equal(0, responderCounter); - assert.equal(0, Ajax.activeRequestCount); - - new Ajax.Request('/fixtures/content.html', { - method: 'get', - parameters: 'pet=monkey' - }); - - assert.equal(1, responderCounter); - assert.equal(1, Ajax.activeRequestCount); - - setTimeout(function () { - assert.equal(3, responderCounter); - assert.equal(0, Ajax.activeRequestCount); - done(); - }, 1000); - - }); - - test('eval response should be called before onComplete', function () { - assert.equal('', $('content').innerHTML); - assert.equal(0, Ajax.activeRequestCount); - - new Ajax.Request('/fixtures/hello.js', extendDefault({ - onComplete: function(response) { - assert.notEqual('', $('content').innerHTML); - } - })); - assert.equal(0, Ajax.activeRequestCount); - - var h2 = $('content').firstChild; - assert.equal('Hello world!', h2.innerHTML); - }); - - test('Content-Type set for obscure verbs', function () { - new Ajax.Request('/inspect', extendDefault({ - method: 'put', - contentType: 'application/bogus', - onComplete: function (response) { - assert.equal( - 'application/bogus; charset=UTF-8', - response.responseJSON.headers['content-type'] - ); - } - })); - }); - - test('verbs with bodies', function () { - var verbs = $w('post put patch'); - verbs.each(function (verb) { - new Ajax.Request('/inspect', extendDefault({ - method: verb, - body: 'foo=foo&bar=bar', - onSuccess: function (response) { - var body = response.responseJSON.body; - assert.equal('foo=foo&bar=bar', body, verb + ' should send body'); - }, - onFailure: function () { - assert(false, verb + ' should send body'); - } - })); - }); - }); - - test('verbs without bodies', function () { - var verbs = $w('get head options delete'); - - verbs.each(function (verb) { - new Ajax.Request('/inspect', extendDefault({ - method: verb, - onSuccess: function () { - assert(true, verb + ' method should work'); - }, - onFailure: function () { - assert(false, verb + ' method should work'); - } - })); - }); - }); - - test('onCreate callback', function () { - new Ajax.Request('/fixtures/content.html', extendDefault({ - onCreate: function (transport) { - assert.equal(0, transport.readyState); - }, - onComplete: function (transport) { - assert.notEqual(0, transport.readyState); - } - })); - }); - - test('evalJS', function () { - $('content').update(); - new Ajax.Request('/response', extendDefault({ - parameters: Fixtures.Ajax.js, - onComplete: function (transport) { - var h2 = $('content').firstChild; - assert.equal('Hello world!', h2.innerHTML); - } - })); - - $('content').update(); - new Ajax.Request('/response', extendDefault({ - evalJS: false, - parameters: Fixtures.Ajax.js, - onComplete: function () { - assert.equal('', $('content').innerHTML); - } - })); - - $('content').update(); - new Ajax.Request("/fixtures/hello.js", extendDefault({ - evalJS: 'force', - onComplete: function(transport) { - var h2 = $('content').firstChild; - assert.equal('Hello world!', h2.innerHTML); - } - })); - - }); - - test('callbacks', function () { - var options = extendDefault({ - onCreate: function (transport) { - assert.isInstanceOf(transport, Ajax.Response); - } - }); - - Ajax.Request.Events.each(function (state) { - options['on' + state] = options.onCreate; - }); - - new Ajax.Request('/fixtures/content.html', options); - }); - - test('response text', function () { - new Ajax.Request('/fixtures/empty.html', extendDefault({ - onComplete: function (transport) { - assert.equal('', transport.responseText); - } - })); - - new Ajax.Request('/fixtures/content.html', extendDefault({ - onComplete: function (transport) { - assert.equal(sentence, transport.responseText.toLowerCase()); - } - })); - }); - - test('responseXML', function () { - new Ajax.Request('/response', extendDefault({ - parameters: Fixtures.Ajax.xml, - onComplete: function (transport) { - assert.equal( - 'foo', - transport.responseXML.getElementsByTagName('name')[0].getAttribute('attr') - ); - } - })); - }); - - test('responseJSON', function () { - new Ajax.Request('/response', extendDefault({ - parameters: Fixtures.Ajax.json, - onComplete: function (transport) { - assert.equal(123, transport.responseJSON.test); - } - })); - - new Ajax.Request('/response', extendDefault({ - parameters: { - 'Content-Length': 0, - 'Content-Type': 'application/json' - }, - onComplete: function (transport) { - assert.isNull(transport.responseJSON); - } - })); - - new Ajax.Request('/response', extendDefault({ - evalJSON: false, - parameters: Fixtures.Ajax.json, - onComplete: function (transport) { - assert.isNull(transport.responseJSON); - } - })); - - new Ajax.Request('/response', extendDefault({ - sanitizeJSON: true, - parameters: Fixtures.Ajax.invalidJson, - onException: function (request, error) { - assert.equal('SyntaxError', error.name); - } - })); - - new Ajax.Request('/fixtures/data.json', extendDefault({ - evalJSON: 'force', - onComplete: function (transport) { - assert.equal(123, transport.responseJSON.test); - } - })); - }); - - test('headerJSON', function () { - new Ajax.Request('/response', extendDefault({ - parameters: Fixtures.Ajax.headerJson, - onComplete: function (transport, json) { - assert.equal('hello #éà', transport.headerJSON.test); - assert.equal('hello #éà', json.test); - } - })); - - new Ajax.Request('/response', extendDefault({ - onComplete: function (transport, json) { - assert.isNull(transport.headerJSON); - assert.isNull(json); - } - })); - }); - - test('getHeader', function () { - new Ajax.Request('/response', extendDefault({ - parameters: { 'X-TEST': 'some value' }, - onComplete: function (transport) { - assert.equal('some value', transport.getHeader('X-Test')); - assert.isNull(transport.getHeader('X-Non-Existent')); - } - })); - }); - - test('parameters can be a hash', function () { - new Ajax.Request('/response', extendDefault({ - parameters: $H({ one: "two", three: "four" }), - onComplete: function (transport) { - assert.equal('two', transport.getHeader('one')); - assert.equal('four', transport.getHeader('three')); - assert.isNull(transport.getHeader('toObject')); - } - })); - }); - - test('parameters string order is preserved', function () { - new Ajax.Request('/inspect', extendDefault({ - parameters: "cool=1&bad=2&cool=3&bad=4", - method: 'post', - onComplete: function (transport) { - var bodyWithoutWart = - transport.responseJSON.body.match(/((?:(?!&_=$).)*)/)[1]; - assert.equal('cool=1&bad=2&cool=3&bad=4', bodyWithoutWart); - } - })); - }); - - test('isSameOrigin', function () { - var isSameOrigin = Ajax.Request.prototype.isSameOrigin; - - assert(isSameOrigin.call({ url: '/foo/bar.html' }), - '/foo/bar.html should be same-origin'); - assert(isSameOrigin.call({ url: window.location.toString() }), - 'current window location should be same-origin'); - assert(!isSameOrigin.call({ url: 'http://example.com' }), - 'example.com should not be same-origin'); - - Ajax.Request.prototype.isSameOrigin = function () { - return false; - }; - - $('content').update('same origin policy'); - - new Ajax.Request('/response', extendDefault({ - parameters: Fixtures.Ajax.js, - onComplete: function (transport) { - assert.equal('same origin policy', $('content').innerHTML); - } - })); - - new Ajax.Request('/response', extendDefault({ - parameters: Fixtures.Ajax.invalidJson, - onException: function (request, error) { - assert.equal('SyntaxError', error.name); - } - })); - - new Ajax.Request('/response', extendDefault({ - parameters: { 'X-JSON': '{});window.attacked = true;({}' }, - onException: function (request, error) { - assert.equal('SyntaxError', error.name); - } - })); - - Ajax.Request.prototype.isSameOrigin = isSameOrigin; - }); - - test('can omit content-type', function () { - new Ajax.Request('/inspect', extendDefault({ - method: 'post', - contentType: false, - onSuccess: function (response) { - // If we omit Content-Type, the browser will provide its own. - var contentType = response.responseJSON.headers['content-type']; - assert(contentType.indexOf('text/plain') > -1); - } - })); - }); -}); - diff --git a/test/unit/tests/array.test.js b/test/unit/tests/array.test.js deleted file mode 100644 index ea6d1acfc..000000000 --- a/test/unit/tests/array.test.js +++ /dev/null @@ -1,355 +0,0 @@ -var globalArgsTest = 'nothing to see here'; - -suite('Array', function () { - this.name = 'array'; - - test('$A', function () { - assert.enumEqual([], $A({})); - }); - - test('$A (on arguments)', function () { - function toArrayOnArguments(){ - globalArgsTest = $A(arguments); - } - toArrayOnArguments(); - assert.enumEqual([], globalArgsTest); - toArrayOnArguments('foo'); - assert.enumEqual(['foo'], globalArgsTest); - toArrayOnArguments('foo','bar'); - assert.enumEqual(['foo','bar'], globalArgsTest); - }); - - test('$A (on NodeList)', function () { - // direct HTML - assert.equal(3, $A($('test_node').childNodes).length); - - // DOM - var element = document.createElement('div'); - element.appendChild(document.createTextNode('22')); - (2).times(function(){ element.appendChild(document.createElement('span')); }); - assert.equal(3, $A(element.childNodes).length); - - // HTML String - element = document.createElement('div'); - $(element).update('22 2; - })); - assert(![1,2,3,4,5].any(function(value) { - return value > 5; - })); - - var x = [1,2,3], traversed = []; - delete x[1]; - x.any(function(val) { traversed.push(val); }); - assert.enumEqual([1, 3], traversed); - assert.strictEqual(2, traversed.length); - }); - - test('#any (used as generic)', function () { - assert(Array.prototype.any.call({ 0:false, 1:true, length:2 })); - assert(!Array.prototype.any.call({ 0:false, 1:false, length:2 })); - }); - - test('#all', function () { - assert([].all()); - - assert([true, true, true].all()); - assert(![true, false, false].all()); - assert(![false, false, false].all()); - - assert([1,2,3,4,5].all(function(value) { - return value > 0; - })); - assert(![1,2,3,4,5].all(function(value) { - return value > 1; - })); - - var x = [1,2,3], traversed = []; - delete x[1]; - x.all(function(val) { traversed.push(val); return true; }); - assert.enumEqual([1, 3], traversed); - assert.strictEqual(2, traversed.length); - }); - - test('#all (used as generic)', function () { - assert(Array.prototype.all.call({ 0:true, 1:true, length:2 })); - assert(!Array.prototype.all.call({ 0:false, 1:true, length:2 })); - }); - - test('#entries (should be either nonexistent or native)', function () { - assert(Array.prototype.entries !== Enumerable.entries); - }); - -}); diff --git a/test/unit/tests/base.test.js b/test/unit/tests/base.test.js deleted file mode 100644 index 6c6925164..000000000 --- a/test/unit/tests/base.test.js +++ /dev/null @@ -1,57 +0,0 @@ - -suite('Base', function () { - - this.name = 'base'; - - test('Browser detection', function () { - - var results = $H(Prototype.Browser).map(function (engine) { - return engine; - }).partition(function (engine) { - return engine[1] === true; - }); - var trues = results[0], falses = results[1]; - - info('User agent string is: ' + navigator.userAgent); - - // It's OK for there to be two true values if we're on MobileSafari, - // since it's also a WebKit browser. - if (Prototype.Browser.MobileSafari) { - assert(trues.size() === 2, 'MobileSafari should also identify as WebKit.'); - } else { - assert(trues.size() === 0 || trues.size() === 1, - 'There should be only one or no browser detected.'); - } - - // we should have definite trues or falses here - trues.each(function(result) { - assert(result[1] === true); - }, this); - falses.each(function(result) { - assert(result[1] === false); - }, this); - - var ua = navigator.userAgent; - - if (ua.indexOf('AppleWebKit/') > -1) { - info('Running on WebKit'); - assert(Prototype.Browser.WebKit); - } - - if (Object.prototype.toString.call(window.opera) === '[object Opera]') { - info('Running on Opera'); - assert(Prototype.Browser.Opera); - } - - if (ua.indexOf('MSIE') > -1) { - info('Running on IE'); - assert(Prototype.Browser.IE); - } - - if (ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') === -1) { - info('Running on Gecko'); - assert(Prototype.Browser.Gecko); - } - }); - -}); \ No newline at end of file diff --git a/test/unit/tests/class.test.js b/test/unit/tests/class.test.js deleted file mode 100644 index bb41a468a..000000000 --- a/test/unit/tests/class.test.js +++ /dev/null @@ -1,223 +0,0 @@ -// base class -var Animal = Class.create({ - initialize: function(name) { - this.name = name; - }, - name: "", - eat: function() { - return this.say("Yum!"); - }, - say: function(message) { - return this.name + ": " + message; - } -}); - -// subclass that augments a method -var Cat = Class.create(Animal, { - eat: function($super, food) { - if (food instanceof Mouse) return $super(); - else return this.say("Yuk! I only eat mice."); - } -}); - -// empty subclass -var Mouse = Class.create(Animal, {}); - -//mixins -var Sellable = { - getValue: function(pricePerKilo) { - return this.weight * pricePerKilo; - }, - - inspect: function() { - return '#'.interpolate(this); - } -}; - -var Reproduceable = { - reproduce: function(partner) { - if (partner.constructor != this.constructor || partner.sex == this.sex) - return null; - var weight = this.weight / 10, sex = Math.random(1).round() ? 'male' : 'female'; - return new this.constructor('baby', weight, sex); - } -}; - -// base class with mixin -var Plant = Class.create(Sellable, { - initialize: function(name, weight) { - this.name = name; - this.weight = weight; - }, - - inspect: function() { - return '#'.interpolate(this); - } -}); - -// subclass with mixin -var Dog = Class.create(Animal, Reproduceable, { - initialize: function($super, name, weight, sex) { - this.weight = weight; - this.sex = sex; - $super(name); - } -}); - -// subclass with mixins -var Ox = Class.create(Animal, Sellable, Reproduceable, { - initialize: function($super, name, weight, sex) { - this.weight = weight; - this.sex = sex; - $super(name); - }, - - eat: function(food) { - if (food instanceof Plant) - this.weight += food.weight; - }, - - inspect: function() { - return '#'.interpolate(this); - } -}); - - - - -suite("Class", function () { - this.name = 'class'; - - test('create', function () { - assert(Object.isFunction(Animal), 'Animal is not a constructor'); - }); - - test('instantiation', function () { - var pet = new Animal('Nibbles'); - assert.equal('Nibbles', pet.name, 'property not initialized'); - assert.equal('Nibbles: Hi!', pet.say('Hi!')); - assert.equal(Animal, pet.constructor, 'bad constructor reference'); - assert.isUndefined(pet.superclass); - - var Empty = Class.create(); - assert.equal('object', typeof new Empty); - }); - - test('inheritance', function () { - var tom = new Cat('Tom'); - assert.equal(Cat, tom.constructor, 'bad constructor reference'); - assert.equal(Animal, tom.constructor.superclass, 'bad superclass reference'); - assert.equal('Tom', tom.name); - assert.equal('Tom: meow', tom.say('meow')); - assert.equal('Tom: Yuk! I only eat mice.', tom.eat(new Animal)); - }); - - test('superclass method call', function () { - var tom = new Cat('Tom'); - assert.equal('Tom: Yum!', tom.eat(new Mouse)); - - var Dodo = Class.create(Animal, { - initialize: function ($super, name) { - $super(name); - this.extinct = true; - }, - - say: function ($super, message) { - return $super(message) + " honk honk"; - } - }); - - var gonzo = new Dodo('Gonzo'); - assert.equal('Gonzo', gonzo.name); - assert(gonzo.extinct, 'Dodo birds should be extinct'); - assert.equal('Gonzo: hello honk honk', gonzo.say('hello')); - }); - - test('addMethods', function () { - var tom = new Cat('Tom'); - var jerry = new Mouse('Jerry'); - - Animal.addMethods({ - sleep: function () { - return this.say('ZZZ'); - } - }); - - Mouse.addMethods({ - sleep: function ($super) { - return $super() + " ... no, can't sleep! Gotta steal cheese!"; - }, - - escape: function (cat) { - return this.say('(from a mousehole) Take that, ' + cat.name + '!'); - } - }); - - assert.equal('Tom: ZZZ', tom.sleep(), - 'added instance method not available to subclass'); - assert.equal("Jerry: ZZZ ... no, can't sleep! Gotta steal cheese!", - jerry.sleep()); - assert.equal("Jerry: (from a mousehole) Take that, Tom!", - jerry.escape(tom)); - - // Ensure that a method has not propagated _up_ the prototype chain. - assert.isUndefined(tom.escape); - assert.isUndefined(new Animal().escape); - - Animal.addMethods({ - sleep: function () { - return this.say('zZzZ'); - } - }); - - assert.equal("Jerry: zZzZ ... no, can't sleep! Gotta steal cheese!", - jerry.sleep()); - - }); - - test('base class with mixin', function () { - var grass = new Plant('grass', 3); - assert.respondsTo('getValue', grass); - assert.equal('#', grass.inspect()); - }); - - test('subclass with mixin', function () { - var snoopy = new Dog('Snoopy', 12, 'male'); - assert.respondsTo('reproduce', snoopy); - }); - - test('subclass with mixins', function () { - var cow = new Ox('cow', 400, 'female'); - assert.equal('#', cow.inspect()); - assert.respondsTo('reproduce', cow); - assert.respondsTo('getValue', cow); - }); - - test('class with toString and valueOf methods', function () { - var Foo = Class.create({ - toString: function() { return "toString"; }, - valueOf: function() { return "valueOf"; } - }); - - var Bar = Class.create(Foo, { - valueOf: function() { return "myValueOf"; } - }); - - var Parent = Class.create({ - m1: function(){ return 'm1'; }, - m2: function(){ return 'm2'; } - }); - var Child = Class.create(Parent, { - m1: function($super) { return 'm1 child'; }, - m2: function($super) { return 'm2 child'; } - }); - - assert(new Child().m1.toString().indexOf('m1 child') > -1); - - assert.equal("toString", new Foo().toString()); - assert.equal("valueOf", new Foo().valueOf() ); - assert.equal("toString", new Bar().toString()); - assert.equal("myValueOf", new Bar().valueOf() ); - }); - -}); \ No newline at end of file diff --git a/test/unit/tests/date.test.js b/test/unit/tests/date.test.js deleted file mode 100644 index 8a13c3c80..000000000 --- a/test/unit/tests/date.test.js +++ /dev/null @@ -1,18 +0,0 @@ -suite('Date', function () { - this.name = 'date'; - - test('#toJSON', function () { - assert.match( - new Date(Date.UTC(1970, 0, 1)).toJSON(), - /^1970-01-01T00:00:00(\.000)?Z$/ - ); - }); - - test('#toISOString', function () { - assert.match( - new Date(Date.UTC(1970, 0, 1)).toISOString(), - /^1970-01-01T00:00:00(\.000)?Z$/ - ); - }); - -}); \ No newline at end of file diff --git a/test/unit/tests/dom.test.js b/test/unit/tests/dom.test.js deleted file mode 100644 index 1ef310a33..000000000 --- a/test/unit/tests/dom.test.js +++ /dev/null @@ -1,1543 +0,0 @@ -var testVar = 'to be updated', testVar2 = ''; - -Element.addMethods({ - hashBrowns: function(element) { return 'hash browns'; } -}); - -Element.addMethods("LI", { - pancakes: function(element) { return "pancakes"; } -}); - -Element.addMethods("DIV", { - waffles: function(element) { return "waffles"; } -}); - -Element.addMethods($w("li div"), { - orangeJuice: function(element) { return "orange juice"; } -}); - - -function getInnerHTML (id) { - return $(id).innerHTML.toString().toLowerCase().gsub(/[\r\n\t]/, ''); -} - -function createParagraph (text) { - var p = document.createElement('p'); - p.appendChild(document.createTextNode(text)); - return p; -} - -var RESIZE_DISABLED = false; - -function simulateClick(node) { - var oEvent; - if (document.createEvent) { - oEvent = document.createEvent('MouseEvents'); - oEvent.initMouseEvent('click', true, true, document.defaultView, - 0, 0, 0, 0, 0, false, false, false, false, 0, node); - node.dispatchEvent(oEvent); - } else { - node.click(); - } -} - -var documentViewportProperties = null; - - -suite('DOM', function () { - this.name = 'dom'; - - setup(function () { - - if (documentViewportProperties) return; - - // Based on properties check from http://www.quirksmode.org/viewport/compatibility.html. - - documentViewportProperties = { - properties: [ - 'self.pageXOffset', 'self.pageYOffset', - 'self.screenX', 'self.screenY', - 'self.innerHeight', 'self.innerWidth', - 'self.outerHeight', 'self.outerWidth', - 'self.screen.height', 'self.screen.width', - 'self.screen.availHeight', 'self.screen.availWidth', - 'self.screen.availTop', 'self.screen.availLeft', - 'self.screen.Top', 'self.screen.Left', - 'self.screenTop', 'self.screenLeft', - 'document.body.clientHeight', 'document.body.clientWidth', - 'document.body.scrollHeight', 'document.body.scrollWidth', - 'document.body.scrollLeft', 'document.body.scrollTop', - 'document.body.offsetHeight', 'document.body.offsetWidth', - 'document.body.offsetTop', 'document.body.offsetLeft' - ].inject([], function (properties, prop) { - if (!self.screen && prop.include('self.screen')) return; - if (!document.body && prop.include('document.body')) return; - - properties.push(prop); - - if (prop.include('body') && document.documentElement) { - properties.push(prop.sub('.body', '.documentElement')); - } - - return properties; - }), - - inspect: function () { - var props = []; - this.properties.each(function (prop) { - if (eval(prop)) props[prop] = eval(prop); - }, this); - return props; - } - }; - }); - - - - test('$', function () { - assert.isUndefined($(), '$() should be undefined'); - - assert.isNull(document.getElementById('noWayThisIDExists'), - 'nonexistent ID should return null from getElementById'); - - assert.isNull($('noWayThisIDExists'), - 'nonexistent ID should return null from $'); - - assert.strictEqual(document.getElementById('testdiv'), $('testdiv'), - 'getElementById and $ should return the same element'); - - assert.deepEqual( - [ $('testdiv'), $('container') ], - $('testdiv', 'container') - ); - - assert.deepEqual( - [ $('testdiv'), null, $('container') ], - $('testdiv', 'noWayThisIDExists', 'container') - ); - - var elt = $('testdiv'); - - assert.strictEqual(elt, $(elt)); - assert.respondsTo('hide', elt); - assert.respondsTo('childOf', elt); - }); - - - test('.insert (with HTML)', function () { - - Element.insert('insertions-main', { - before:'

      before text

      more testing

      ' - }); - assert(getInnerHTML('insertions-container').startsWith('

      before text

      more testing

      ')); - - Element.insert('insertions-main', { - after:'

      after text

      more testing

      ' - }); - assert(getInnerHTML('insertions-container').endsWith('

      after text

      more testing

      ')); - - Element.insert('insertions-main', { - top:'

      top text.

      more testing

      ' - }); - assert(getInnerHTML('insertions-main').startsWith('

      top text.

      more testing

      ')); - - Element.insert('insertions-main', { - bottom:'

      bottom text.

      more testing

      ' - }); - assert(getInnerHTML('insertions-main').endsWith('

      bottom text.

      more testing

      ')); - - }); - - - test('.insert (with DOM node)', function () { - Element.insert('insertions-node-main', { - before: createParagraph('node before') - }); - assert(getInnerHTML('insertions-node-container').startsWith('

      node before

      ')); - - Element.insert('insertions-node-main', { - after: createParagraph('node after') - }); - assert(getInnerHTML('insertions-node-container').endsWith('

      node after

      ')); - - Element.insert('insertions-node-main', { - top: createParagraph('node top') - }); - assert(getInnerHTML('insertions-node-main').startsWith('

      node top

      ')); - - Element.insert('insertions-node-main', { - bottom: createParagraph('node bottom')} - ); - assert(getInnerHTML('insertions-node-main').endsWith('

      node bottom

      ')); - - assert.equal( - $('insertions-node-main'), - $('insertions-node-main').insert(document.createElement('p')), - 'insert should return the original node' - ); - }); - - - test('.insert (with toElement method)', function () { - Element.insert('insertions-node-main', { - toElement: createParagraph.curry('toElement') - }); - assert(getInnerHTML('insertions-node-main').endsWith('

      toelement

      ')); - - Element.insert('insertions-node-main', { - bottom: { toElement: createParagraph.curry('bottom toElement') } - }); - assert(getInnerHTML('insertions-node-main').endsWith('

      bottom toelement

      ')); - }); - - - test('.insert (with toHTML method)', function () { - Element.insert('insertions-node-main', { - toHTML: function() { return '

      toHTML

      '; } - }); - assert(getInnerHTML('insertions-node-main').endsWith('

      tohtml

      ')); - - Element.insert('insertions-node-main', { - bottom: { - toHTML: function() { return '

      bottom toHTML

      '; } - } - }); - assert(getInnerHTML('insertions-node-main').endsWith('

      bottom tohtml

      ')); - }); - - test('.insert (with non-string)', function () { - Element.insert('insertions-main', { bottom: 3 }); - assert(getInnerHTML('insertions-main').endsWith('3')); - }); - - test('.insert (in tables)', function () { - Element.insert('second_row', { - after:'Third Row' - }); - assert($('second_row').parentNode == $('table'), - 'table rows should be inserted correctly'); - - $('a_cell').insert({ top: 'hello world' }); - assert($('a_cell').innerHTML.startsWith('hello world'), - 'content should be inserted into table cells correctly'); - - $('a_cell').insert({ after: 'hi planet' }); - assert.equal('hi planet', $('a_cell').next().innerHTML, - 'table cells should be inserted after existing table cells correctly'); - - $('table_for_insertions').insert('a cell!'); - assert($('table_for_insertions').innerHTML.gsub('\r\n', '').toLowerCase().include('a cell!'), - 'complex content should be inserted into a table correctly'); - - $('row_1').insert({ after:'last' }); - assert.equal('last', $A($('table_for_row_insertions').getElementsByTagName('tr')).last().lastChild.innerHTML, - 'complex content should be inserted after a table row correctly'); - }); - - test('.insert (in select)', function () { - var selectTop = $('select_for_insert_top'); - var selectBottom = $('select_for_insert_bottom'); - - selectBottom.insert(''); - assert.equal('option 45', selectBottom.getValue()); - selectTop.insert({top:''}); - assert.equal(4, selectTop.options.length); - }); - - test('#insert', function () { - $('element-insertions-main').insert({before:'some text before'}); - assert(getInnerHTML('element-insertions-container').startsWith('some text before'), 'some text before'); - $('element-insertions-main').insert({after:'some text after'}); - assert(getInnerHTML('element-insertions-container').endsWith('some text after'), 'some text after'); - $('element-insertions-main').insert({top:'some text top'}); - assert(getInnerHTML('element-insertions-main').startsWith('some text top'), 'some text top'); - $('element-insertions-main').insert({bottom:'some text bottom'}); - assert(getInnerHTML('element-insertions-main').endsWith('some text bottom'), 'some text bottom'); - - $('element-insertions-main').insert('some more text at the bottom'); - assert(getInnerHTML('element-insertions-main').endsWith('some more text at the bottom'), - 'some more text at the bottom'); - - $('element-insertions-main').insert({TOP:'some text uppercase top'}); - assert(getInnerHTML('element-insertions-main').startsWith('some text uppercase top'), 'some text uppercase top'); - - $('element-insertions-multiple-main').insert({ - top:'1', bottom:2, before: new Element('p').update('3'), after:'4' - }); - assert(getInnerHTML('element-insertions-multiple-main').startsWith('1'), '1'); - assert(getInnerHTML('element-insertions-multiple-main').endsWith('2'), '2'); - assert(getInnerHTML('element-insertions-multiple-container').startsWith( - '

      3

      '), '

      3

      '); - assert(getInnerHTML('element-insertions-multiple-container').endsWith('4'), '4'); - - $('element-insertions-main').update('test'); - $('element-insertions-main').insert(null); - $('element-insertions-main').insert({bottom:null}); - assert.equal('test', getInnerHTML('element-insertions-main'), 'should insert nothing when called with null'); - $('element-insertions-main').insert(1337); - assert.equal('test1337', getInnerHTML('element-insertions-main'), 'should coerce to string when called with number'); - }); - - - test('#insert (with new Element)', function () { - var container = new Element('div'), element = new Element('div'); - container.insert(element); - - element.insert({ before: '

      a paragraph

      ' }); - assert.equal('

      a paragraph

      ', getInnerHTML(container)); - element.insert({ after: 'some text' }); - assert.equal('

      a paragraph

      some text', getInnerHTML(container)); - - element.insert({ top: '

      a paragraph

      ' }); - assert.equal('

      a paragraph

      ', getInnerHTML(element)); - element.insert('some text'); - assert.equal('

      a paragraph

      some text', getInnerHTML(element)); - - }); - - - test('Insertion (backwards-compatibility)', function () { - new Insertion.Before('element-insertions-main', 'some backward-compatibility testing before'); - assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing before')); - new Insertion.After('element-insertions-main', 'some backward-compatibility testing after'); - assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing after')); - new Insertion.Top('element-insertions-main', 'some backward-compatibility testing top'); - assert(getInnerHTML('element-insertions-main').startsWith('some backward-compatibility testing top')); - new Insertion.Bottom('element-insertions-main', 'some backward-compatibility testing bottom'); - assert(getInnerHTML('element-insertions-main').endsWith('some backward-compatibility testing bottom')); - }); - - test('#wrap', function () { - var element = $('wrap'), parent = document.createElement('div'); - element.wrap(); - assert(getInnerHTML('wrap-container').startsWith('
      \ntestVar="hello!";\n'); - assert.equal('hello from div!', $('testdiv').innerHTML); - - wait(100, done, function () { - assert.equal('hello!', testVar); - - Element.update('testdiv','another hello from div!\n" - - str.evalScripts.bind(str).defer(); - - wait(50, done, function() { - assert(window.deferBoundProperlyOnString); - done(); - }); - }); - }); - }); - }); - - test('#methodize', function () { - var Foo = { bar: function(baz) { return baz; } }; - var baz = { quux: Foo.bar.methodize() }; - - assert.equal(Foo.bar.methodize(), baz.quux); - assert.equal(baz, Foo.bar(baz)); - assert.equal(baz, baz.quux()); - }); - - test('#bindAsEventListener', function () { - for (var i = 0; i < 10; ++i){ - var div = document.createElement('div'); - div.setAttribute('id','test-'+i); - document.body.appendChild(div); - var tobj = new TestObj(); - var eventTest = { test: true }; - var call = tobj.assertingEventHandler.bindAsEventListener(tobj, - assert.equal.bind(assert, eventTest), - assert.equal.bind(assert, arg1), - assert.equal.bind(assert, arg2), - assert.equal.bind(assert, arg3), arg1, arg2, arg3 ); - call(eventTest); - } - }); - -}); diff --git a/test/unit/tests/hash.test.js b/test/unit/tests/hash.test.js deleted file mode 100644 index 437baedd6..000000000 --- a/test/unit/tests/hash.test.js +++ /dev/null @@ -1,240 +0,0 @@ -Fixtures.Hash = { - one: { a: 'A#' }, - - many: { - a: 'A', - b: 'B', - c: 'C', - d: 'D#' - }, - - functions: { - quad: function(n) { return n*n; }, - plus: function(n) { return n+n; } - }, - - multiple: { color: $w('r g b') }, - multiple_nil: { color: ['r', null, 'g', undefined, 0] }, - multiple_all_nil: { color: [null, undefined] }, - multiple_empty: { color: [] }, - multiple_special: { 'stuff[]': $w('$ a ;') }, - - value_undefined: { a:"b", c:undefined }, - value_null: { a:"b", c:null }, - value_zero: { a:"b", c:0 } -}; - - -/// - - -suite('Hash', function () { - this.name = 'hash'; - - test('#set', function () { - var h = $H({a: 'A'}); - - assert.equal('B', h.set('b', 'B')); - assert.hashEqual({a: 'A', b: 'B'}, h); - - assert.isUndefined(h.set('c')); - assert.hashEqual({a: 'A', b: 'B', c: undefined}, h); - }); - - test('#get', function () { - var h = $H({a: 'A'}); - assert.equal('A', h.get('a')); - assert.isUndefined(h.a); - assert.isUndefined($H({}).get('a')); - - assert.isUndefined($H({}).get('toString')); - assert.isUndefined($H({}).get('constructor')); - }); - - test('#unset', function () { - var hash = $H(Fixtures.Hash.many); - assert.equal('B', hash.unset('b')); - assert.hashEqual({a:'A', c: 'C', d:'D#'}, hash); - assert.isUndefined(hash.unset('z')); - assert.hashEqual({a:'A', c: 'C', d:'D#'}, hash); - // not equivalent to Hash#remove - assert.equal('A', hash.unset('a', 'c')); - assert.hashEqual({c: 'C', d:'D#'}, hash); - }); - - test('#toObject', function () { - var hash = $H(Fixtures.Hash.many), object = hash.toObject(); - assert.isInstanceOf(object, Object); - assert.hashEqual(Fixtures.Hash.many, object); - assert.notStrictEqual(Fixtures.Hash.many, object); - hash.set('foo', 'bar'); - assert.hashNotEqual(object, hash.toObject()); - }); - - test('new Hash', function () { - var object = Object.clone(Fixtures.Hash.one); - var h = new Hash(object), h2 = $H(object); - assert.isInstanceOf(h, Hash); - assert.isInstanceOf(h2, Hash); - - assert.hashEqual({}, new Hash()); - assert.hashEqual(object, h); - assert.hashEqual(object, h2); - - h.set('foo', 'bar'); - assert.hashNotEqual(object, h); - - var clone = $H(h); - assert.isInstanceOf(clone, Hash); - assert.hashEqual(h, clone); - h.set('foo', 'foo'); - assert.hashNotEqual(h, clone); - assert.strictEqual($H, Hash.from); - }); - - test('#keys', function () { - assert.enumEqual([], $H({}).keys()); - assert.enumEqual(['a'], $H(Fixtures.Hash.one).keys()); - assert.enumEqual($w('a b c d'), $H(Fixtures.Hash.many).keys().sort()); - assert.enumEqual($w('plus quad'), $H(Fixtures.Hash.functions).keys().sort()); - }); - - test('#values', function () { - assert.enumEqual([], $H({}).values()); - assert.enumEqual(['A#'], $H(Fixtures.Hash.one).values()); - assert.enumEqual($w('A B C D#'), $H(Fixtures.Hash.many).values().sort()); - assert.enumEqual($w('function function'), - $H(Fixtures.Hash.functions).values().map(function(i){ return typeof i; })); - assert.equal(9, $H(Fixtures.Hash.functions).get('quad')(3)); - assert.equal(6, $H(Fixtures.Hash.functions).get('plus')(3)); - }); - - test('#index', function () { - assert.isUndefined($H().index('foo')); - - assert('a', $H(Fixtures.Hash.one).index('A#')); - assert('a', $H(Fixtures.Hash.many).index('A')); - assert.isUndefined($H(Fixtures.Hash.many).index('Z')); - - var hash = $H({a:1,b:'2',c:1}); - assert(['a','c'].include(hash.index(1))); - assert.isUndefined(hash.index('1')); - }); - - test('#merge', function () { - var h = $H(Fixtures.Hash.many); - assert.notStrictEqual(h, h.merge()); - assert.notStrictEqual(h, h.merge({})); - assert.isInstanceOf(h.merge(), Hash); - assert.isInstanceOf(h.merge({}), Hash); - assert.hashEqual(h, h.merge()); - assert.hashEqual(h, h.merge({})); - assert.hashEqual(h, h.merge($H())); - assert.hashEqual({a:'A', b:'B', c:'C', d:'D#', aaa:'AAA' }, h.merge({aaa: 'AAA'})); - assert.hashEqual({a:'A#', b:'B', c:'C', d:'D#' }, h.merge(Fixtures.Hash.one)); - }); - - test('#update', function () { - var h = $H(Fixtures.Hash.many); - assert.strictEqual(h, h.update()); - assert.strictEqual(h, h.update({})); - assert.hashEqual(h, h.update()); - assert.hashEqual(h, h.update({})); - assert.hashEqual(h, h.update($H())); - assert.hashEqual({a:'A', b:'B', c:'C', d:'D#', aaa:'AAA' }, h.update({aaa: 'AAA'})); - assert.hashEqual({a:'A#', b:'B', c:'C', d:'D#', aaa:'AAA' }, h.update(Fixtures.Hash.one)); - }); - - test('#toQueryString', function () { - assert.equal('', $H({}).toQueryString()); - assert.equal('a%23=A', $H({'a#': 'A'}).toQueryString()); - assert.equal('a=A%23', $H(Fixtures.Hash.one).toQueryString()); - assert.equal('a=A&b=B&c=C&d=D%23', $H(Fixtures.Hash.many).toQueryString()); - assert.equal("a=b&c", $H(Fixtures.Hash.value_undefined).toQueryString()); - assert.equal("a=b&c", $H("a=b&c".toQueryParams()).toQueryString()); - assert.equal("a=b+d&c", $H("a=b+d&c".toQueryParams()).toQueryString()); - assert.equal("a=b&c=", $H(Fixtures.Hash.value_null).toQueryString()); - assert.equal("a=b&c=0", $H(Fixtures.Hash.value_zero).toQueryString()); - assert.equal("color=r&color=g&color=b", $H(Fixtures.Hash.multiple).toQueryString()); - assert.equal("color=r&color=&color=g&color&color=0", $H(Fixtures.Hash.multiple_nil).toQueryString()); - assert.equal("color=&color", $H(Fixtures.Hash.multiple_all_nil).toQueryString()); - assert.equal("", $H(Fixtures.Hash.multiple_empty).toQueryString()); - assert.equal("", $H({foo: {}, bar: {}}).toQueryString()); - assert.equal("stuff%5B%5D=%24&stuff%5B%5D=a&stuff%5B%5D=%3B", $H(Fixtures.Hash.multiple_special).toQueryString()); - assert.hashEqual(Fixtures.Hash.multiple_special, $H(Fixtures.Hash.multiple_special).toQueryString().toQueryParams()); - assert.strictEqual(Object.toQueryString, Hash.toQueryString); - - // Serializing newlines and spaces is weird. See: - // http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#h-17.13.4.1 - var complex = "an arbitrary line\n\'something in single quotes followed by a newline\'\r\n" + - "and more text eventually"; - var queryString = $H({ val: complex }).toQueryString(); - var expected = "val=an+arbitrary+line%0D%0A'something+in+single+quotes+followed+by+a+" + - "newline'%0D%0Aand+more+text+eventually"; - assert.equal(expected, queryString, "newlines and spaces should be properly encoded"); - }); - - test('#inspect', function () { - assert.equal('#', $H({}).inspect()); - assert.equal("#", $H(Fixtures.Hash.one).inspect()); - assert.equal("#", $H(Fixtures.Hash.many).inspect()); - }); - - test('#clone', function () { - var h = $H(Fixtures.Hash.many); - assert.hashEqual(h, h.clone()); - assert.isInstanceOf(h.clone(), Hash); - assert.notStrictEqual(h, h.clone()); - }); - - test('#toJSON', function () { - assert.equal('{\"b\":[null,false,true,null],\"c\":{\"a\":\"hello!\"}}', - Object.toJSON({b: [undefined, false, true, undefined], c: {a: 'hello!'}})); - }); - - test('ability to contain any key', function () { - var h = $H({ _each: 'E', map: 'M', keys: 'K', pluck: 'P', unset: 'U' }); - assert.enumEqual($w('_each keys map pluck unset'), h.keys().sort()); - assert.equal('U', h.unset('unset')); - assert.hashEqual({ _each: 'E', map: 'M', keys: 'K', pluck: 'P' }, h); - }); - - test('#toTemplateReplacements', function () { - var template = new Template("#{a} #{b}"), hash = $H({ a: "hello", b: "world" }); - assert.equal("hello world", template.evaluate(hash.toObject())); - assert.equal("hello world", template.evaluate(hash)); - assert.equal("hello", "#{a}".interpolate(hash)); - }); - - test("don't iterate over shadowed properties", function () { - // redundant now that object is systematically cloned. - var FooMaker = function(value) { - this.key = value; - }; - FooMaker.prototype.key = 'foo'; - var foo = new FooMaker('bar'); - assert.equal("key=bar", new Hash(foo).toQueryString()); - assert.equal("key=bar", new Hash(new Hash(foo)).toQueryString()); - }); - - test('#each', function () { - var h = $H({a:1, b:2}); - var result = []; - h.each(function(kv, i){ - result.push(i); - }); - assert.enumEqual([0,1], result); - }); - - -}); - - - - - - - - - - diff --git a/test/unit/tests/layout.test.js b/test/unit/tests/layout.test.js deleted file mode 100644 index d0752b3ab..000000000 --- a/test/unit/tests/layout.test.js +++ /dev/null @@ -1,555 +0,0 @@ -function isDisplayed(element) { - var originalElement = element; - - while (element && element.parentNode) { - var display = element.getStyle('display'); - if (display === 'none') { - return false; - } - element = $(element.parentNode); - } - return true; -} - -var documentViewportProperties = null; - -var RESIZE_DISABLED = false; - -suite("Layout", function(){ - this.name = 'layout'; - - setup(function () { - - if (documentViewportProperties) return; - - // Based on properties check from http://www.quirksmode.org/viewport/compatibility.html. - - documentViewportProperties = { - properties: [ - 'self.pageXOffset', 'self.pageYOffset', - 'self.screenX', 'self.screenY', - 'self.innerHeight', 'self.innerWidth', - 'self.outerHeight', 'self.outerWidth', - 'self.screen.height', 'self.screen.width', - 'self.screen.availHeight', 'self.screen.availWidth', - 'self.screen.availTop', 'self.screen.availLeft', - 'self.screen.Top', 'self.screen.Left', - 'self.screenTop', 'self.screenLeft', - 'document.body.clientHeight', 'document.body.clientWidth', - 'document.body.scrollHeight', 'document.body.scrollWidth', - 'document.body.scrollLeft', 'document.body.scrollTop', - 'document.body.offsetHeight', 'document.body.offsetWidth', - 'document.body.offsetTop', 'document.body.offsetLeft' - ].inject([], function (properties, prop) { - if (!self.screen && prop.include('self.screen')) return; - if (!document.body && prop.include('document.body')) return; - - properties.push(prop); - - if (prop.include('body') && document.documentElement) { - properties.push(prop.sub('.body', '.documentElement')); - } - - return properties; - }), - - inspect: function () { - var props = []; - this.properties.each(function (prop) { - if (eval(prop)) props[prop] = eval(prop); - }, this); - return props; - } - }; - }); - - - test("preCompute argument of layout", function() { - var preComputedLayout = $('box1').getLayout(true), - normalLayout = $('box1').getLayout(); - - // restore normal get method from Hash object - preComputedLayout.get = Hash.prototype.get; - - Element.Layout.PROPERTIES.each(function(key) { - assert.equal(normalLayout.get(key), preComputedLayout.get(key), key); - }); - }); - - test("layout on absolutely-positioned elements", function() { - var layout = $('box1').getLayout(); - - assert.equal(242, layout.get('width'), 'width' ); - assert.equal(555, layout.get('height'), 'height'); - - assert.equal(3, layout.get('border-left'), 'border-left'); - assert.equal(10, layout.get('padding-top'), 'padding-top'); - assert.equal(1020, layout.get('top'), 'top'); - - assert.equal(25, layout.get('left'), 'left'); - }); - - test("layout on elements with display: none and exact width", function() { - var layout = $('box2').getLayout(); - - assert(!isDisplayed($('box2')), 'box should be hidden'); - - assert.equal(500, layout.get('width'), 'width'); - assert.equal( 3, layout.get('border-right'), 'border-right'); - assert.equal( 10, layout.get('padding-bottom'), 'padding-bottom'); - assert.equal(526, layout.get('border-box-width'), 'border-box-width'); - - assert(!isDisplayed($('box2')), 'box should still be hidden'); - }); - - test("layout on elements with negative margins", function() { - var layout = $('box_with_negative_margins').getLayout(); - - assert.equal(-10, layout.get('margin-top') ); - assert.equal( -3, layout.get('margin-left') ); - assert.equal( 2, layout.get('margin-right')); - }); - - test("layout on elements with display: none and width: auto", function() { - var layout = $('box3').getLayout(); - - assert(!isDisplayed($('box3')), 'box should be hidden'); - - assert.equal(364, layout.get('width'), 'width'); - assert.equal(400, layout.get('margin-box-width'), 'margin-box-width'); - assert.equal(390, layout.get('border-box-width'), 'border-box-width'); - assert.equal(3, layout.get('border-right'), 'border-top'); - assert.equal(10, layout.get('padding-bottom'), 'padding-right'); - - // Ensure that we cleaned up after ourselves. - assert(!isDisplayed($('box3')), 'box should still be hidden'); - }); - - test("layout on elements with display: none ancestors",function() { - var layout = $('box4').getLayout(); - - assert(!isDisplayed($('box4')), 'box should be hidden'); - - // Width and height values are nonsensical for deeply-hidden elements. - assert.equal(0, layout.get('width'), 'width of a deeply-hidden element should be 0'); - assert.equal(0, layout.get('margin-box-height'), 'height of a deeply-hidden element should be 0'); - - // But we can still get meaningful values for other measurements. - assert.equal(0, layout.get('border-right'), 'border-top'); - assert.equal(13, layout.get('padding-bottom'), 'padding-right'); - - // Ensure that we cleaned up after ourselves. - assert(!isDisplayed($('box4')), 'box should still be hidden'); - }); - - test("positioning on absolutely-positioned elements", function() { - var layout = $('box5').getLayout(); - - assert.equal(30, layout.get('top'), 'top'); - assert.equal(60, layout.get('right'), 'right (percentage value)'); - - assert.equal(340, layout.get('left'), 'left'); - }); - - test("positioning on absolutely-positioned element with top=0 and left=0", function() { - var layout = $('box6').getLayout(); - - assert.equal(0, layout.get('top'), 'top'); - assert.strictEqual($('box6_parent'), $('box6').getOffsetParent()); - }); - - test("layout on statically-positioned element with percentage width", function() { - var layout = $('box7').getLayout(); - - assert.equal(150, layout.get('width')); - }); - - test("layout on absolutely-positioned element with percentage width", function() { - var layout = $('box8').getLayout(); - - assert.equal(150, layout.get('width')); - }); - - test("layout on fixed-position element with percentage width", function() { - var viewportWidth = document.viewport.getWidth(); - var layout = $('box9').getLayout(); - - function assertNear(v1, v2, message) { - var abs = Math.abs(v1 - v2); - assert(abs <= 1, message + ' (actual: ' + v1 + ', ' + v2 + ')'); - } - - // With percentage widths, we'll occasionally run into rounding - // discrepancies. Assert that the values agree to within 1 pixel. - var vWidth = viewportWidth / 4, eWidth = $('box9').measure('width'); - assertNear.call(this, vWidth, eWidth, 'width (visible)'); - - $('box9').hide(); - assertNear.call(this, vWidth, $('box9').measure('width'), 'width (hidden)'); - $('box9').show(); - }); - - test("#toCSS, #toObject, #toHash", function() { - var layout = $('box6').getLayout(); - var top = layout.get('top'); - - var cssObject = layout.toCSS('top'); - - assert('top' in cssObject, - "layout object should have 'top' property"); - - cssObject = layout.toCSS('top left bottom'); - - $w('top left bottom').each( function(prop) { - assert(prop in cssObject, "layout object should have '" + - prop + "' property"); - }, this); - - var obj = layout.toObject('top'); - assert('top' in obj, - "object should have 'top' property"); - }); - - test("dimensions on absolutely-positioned, hidden elements", function() { - var layout = $('box10').getLayout(); - - assert.equal(278, layout.get('width'), 'width' ); - assert.equal(591, layout.get('height'), 'height'); - }); - - // ELEMENT METHODS - - suite('Element', function () { - - test('#makeClipping, #undoClipping', function () { - var chained = document.createElement('DIV'); - assert.equal(chained, chained.makeClipping()); - assert.equal(chained, chained.makeClipping()); - assert.equal(chained, chained.makeClipping().makeClipping()); - - assert.equal(chained, chained.undoClipping()); - assert.equal(chained, chained.undoClipping()); - assert.equal(chained, chained.undoClipping().makeClipping()); - - ['hidden','visible','scroll'].each( function(overflowValue) { - var element = $('element_with_'+overflowValue+'_overflow'); - - assert.equal(overflowValue, element.getStyle('overflow')); - element.makeClipping(); - assert.equal('hidden', element.getStyle('overflow')); - element.undoClipping(); - assert.equal(overflowValue, element.getStyle('overflow')); - }); - }); - - test('#getHeight', function () { - assert.strictEqual(100, $('dimensions-visible').getHeight()); - assert.strictEqual(100, $('dimensions-display-none').getHeight()); - }); - - test('#getWidth', function () { - assert.strictEqual(200, $('dimensions-visible').getWidth(), '#dimensions-visible'); - assert.strictEqual(200, $('dimensions-display-none').getWidth(), '#dimensions-display-none'); - }); - - test('#getDimensions', function () { - assert.strictEqual(100, $('dimensions-visible').getDimensions().height); - assert.strictEqual(200, $('dimensions-visible').getDimensions().width); - assert.strictEqual(100, $('dimensions-display-none').getDimensions().height); - assert.strictEqual(200, $('dimensions-display-none').getDimensions().width); - - assert.strictEqual(100, $('dimensions-visible-pos-rel').getDimensions().height); - assert.strictEqual(200, $('dimensions-visible-pos-rel').getDimensions().width); - assert.strictEqual(100, $('dimensions-display-none-pos-rel').getDimensions().height); - assert.strictEqual(200, $('dimensions-display-none-pos-rel').getDimensions().width); - - assert.strictEqual(100, $('dimensions-visible-pos-abs').getDimensions().height); - assert.strictEqual(200, $('dimensions-visible-pos-abs').getDimensions().width); - assert.strictEqual(100, $('dimensions-display-none-pos-abs').getDimensions().height); - assert.strictEqual(200, $('dimensions-display-none-pos-abs').getDimensions().width); - - // known failing issue - // assert($('dimensions-nestee').getDimensions().width <= 500, 'check for proper dimensions of hidden child elements'); - - $('dimensions-td').hide(); - assert.strictEqual(100, $('dimensions-td').getDimensions().height); - assert.strictEqual(200, $('dimensions-td').getDimensions().width); - $('dimensions-td').show(); - - $('dimensions-tr').hide(); - assert.strictEqual(100, $('dimensions-tr').getDimensions().height); - assert.strictEqual(200, $('dimensions-tr').getDimensions().width); - $('dimensions-tr').show(); - - $('dimensions-table').hide(); - assert.strictEqual(100, $('dimensions-table').getDimensions().height); - assert.strictEqual(200, $('dimensions-table').getDimensions().width); - }); - - test('#positionedOffset', function () { - assert.enumEqual([10,10], - $('body_absolute').positionedOffset(), '#body_absolute'); - assert.enumEqual([10,10], - $('absolute_absolute').positionedOffset(), '#absolute_absolute'); - assert.enumEqual([10,10], - $('absolute_relative').positionedOffset(), '#absolute_relative'); - assert.enumEqual([0,10], - $('absolute_relative_undefined').positionedOffset(), '#absolute_relative_undefined'); - assert.enumEqual([10,10], - $('absolute_fixed_absolute').positionedOffset(), '#absolute_fixed_absolute'); - - var afu = $('absolute_fixed_undefined'); - assert.enumEqual([afu.offsetLeft, afu.offsetTop], - afu.positionedOffset(), '#absolute_fixed_undefined'); - - var element = new Element('div'), offset = element.positionedOffset(); - assert.enumEqual([0,0], offset, 'new element'); - assert.strictEqual(0, offset.top, 'new element top'); - assert.strictEqual(0, offset.left, 'new element left'); - }); - - test('#cumulativeOffset', function () { - var element = new Element('div'), offset = element.cumulativeOffset(); - assert.enumEqual([0,0], offset, 'new element'); - assert.strictEqual(0, offset.top, 'new element top'); - assert.strictEqual(0, offset.left, 'new element left'); - - var innerEl = new Element('div'), outerEl = new Element('div'); - outerEl.appendChild(innerEl); - assert.enumEqual([0,0], innerEl.cumulativeOffset(), 'new inner element'); - }); - - test('#viewportOffset', function () { - window.scrollTo(0, 0); - - assert.enumEqual([10, 10], - $('body_absolute').viewportOffset()); - assert.enumEqual([20,20], - $('absolute_absolute').viewportOffset()); - assert.enumEqual([20,20], - $('absolute_relative').viewportOffset()); - assert.enumEqual([20,30], - $('absolute_relative_undefined').viewportOffset()); - var element = new Element('div'), offset = element.viewportOffset(); - assert.enumEqual([0,0], offset); - assert.strictEqual(0, offset.top); - assert.strictEqual(0, offset.left); - }); - - test('#getOffsetParent', function () { - assert.equal('body_absolute', $('absolute_absolute').getOffsetParent().id, - '#body_absolute should be parent of #absolute_absolute'); - assert.equal('body_absolute', $('absolute_relative').getOffsetParent().id, - '#body_absolute should be parent of #absolute_relative'); - assert.equal('absolute_relative', $('inline').getOffsetParent().id, - '#absolute_relative should be parent of #inline'); - assert.equal('absolute_relative', $('absolute_relative_undefined').getOffsetParent().id, - '#absolute_relative should be parent of #absolute_relative_undefined'); - - assert.equal(document.body, new Element('div').getOffsetParent(), - 'body should be parent of unattached element'); - - [document, document.body, document.documentElement].each (function(node) { - assert.equal(document.body, Element.getOffsetParent(node)); - }); - }); - - test('#absolutize', function () { - $('notInlineAbsoluted', 'inlineAbsoluted').each(function(elt) { - if ('_originalLeft' in elt) delete elt._originalLeft; - elt.absolutize(); - assert.isUndefined(elt._originalLeft, 'absolutize() did not detect absolute positioning'); - }, this); - // invoking on "absolute" positioned element should return element - var element = $('absolute_fixed_undefined').setStyle({position: 'absolute'}); - assert.equal(element, element.absolutize()); - }); - - test('#relativize', function () { - // invoking on "relative" positioned element should return element - var element = $('absolute_fixed_undefined').setStyle({ - position: 'relative' }); - assert.equal(element, element.relativize()); - }); - - test('#clonePosition (when scrolling the page)', function() { - var opts = { offsetTop: 20, offsetLeft: 0, setWidth: false, setHeight: false }; - - // Before scroll. - $('sub_menu').clonePosition($('main_menu'), opts); - var before = $('sub_menu').viewportOffset().top - $('main_menu').viewportOffset().top; - - // Reset to original position. - $('sub_menu').setStyle({ - position: "absolute", - top: "250px", - left: "250px" - }); - scrollTo(0, 300); - - // After scroll. - $('sub_menu').clonePosition($('main_menu'), opts); - var after = $('sub_menu').viewportOffset()['top'] - $('main_menu').viewportOffset()['top']; - - assert.equal(before, after); - }); - - test('#clonePosition (when element is absolutely positioned and has a non-body offset parent)', function () { - var opts = { offsetTop: 20, offsetLeft: 0, setWidth: false, setHeight: false }; - - var subMenu = $('sub_menu_2'); - var mainMenu = $('main_menu_2'); - - subMenu.clonePosition(mainMenu, opts); - var offset = subMenu.viewportOffset().top - mainMenu.viewportOffset().top; - - assert.equal(offset, 20); - - scrollTo(0, 300); - - subMenu.clonePosition(mainMenu, opts); - offset = subMenu.viewportOffset().top - mainMenu.viewportOffset().top; - assert.equal(offset, 20); - }); - - test('#clonePosition (when element has fixed position)', function () { - var opts = { offsetTop: 20, offsetLeft: 0, setWidth: false, setHeight: false }; - - var subMenu = $('sub_menu_3'); - var mainMenu = $('main_menu_3'); - - subMenu.clonePosition(mainMenu, opts); - var offset = subMenu.viewportOffset().top - mainMenu.viewportOffset().top; - - assert.equal(offset, 20); - - scrollTo(0, 300); - - subMenu.clonePosition(mainMenu, opts); - offset = subMenu.viewportOffset().top - mainMenu.viewportOffset().top; - assert.equal(offset, 20); - - }); - - test('#clonePosition (when elements have the same size)', function() { - var source = $('clone_position_source'); - var target = $('clone_position_target'); - - target.clonePosition(source, { - setHeight: false, - offsetTop: source.offsetHeight - }); - - assert.equal(source.getWidth(), target.getWidth()); - assert.equal(source.getHeight(), target.getHeight()); - }); - - }); // Element - - suite('document.viewport', function () { - - test('#getDimensions', function (done) { - this.timeout(5000); - var original = document.viewport.getDimensions(); - - try { - window.resizeTo(800, 600); - } catch (e) { - info("Can't resize."); - - return done(); - } - wait(1000, done, function() { - var before = document.viewport.getDimensions(); - - var delta = { width: 800 - before.width, height: 600 - before.height }; - - window.resizeBy(50, 50); - wait(1000, done, function() { - var after = document.viewport.getDimensions(); - - // Assume that JavaScript window resizing is disabled if before width - // and after width are the same. - if (before.width === after.width) { - RESIZE_DISABLED = true; - info("SKIPPING REMAINING TESTS (JavaScript window resizing disabled)"); - return done(); - } - - - assert.equal( - before.width + 50, after.width, - "NOTE: YOU MUST ALLOW JAVASCRIPT TO RESIZE YOUR WINDOW FOR THIS TEST TO PASS" - ); - assert.equal( - before.height + 50, after.height, - "NOTE: YOU MUST ALLOW JAVASCRIPT TO RESIZE YOUR WINDOW FOR THIS TEST TO PASS" - ); - - wait(1000, done, function() { - // Restore original dimensions. - window.resizeTo( - original.width + delta.width, - original.height + delta.height - ); - done(); - }); - }); - }); - }); - - test('#getDimensions (should not affect document properties)', function () { - // No properties on the document should be affected when resizing - // an absolutely-positioned (0,0) element to viewport dimensions. - var vd = document.viewport.getDimensions(); - - var before = documentViewportProperties.inspect(); - $('elementToViewportDimensions').setStyle({ height: vd.height + 'px', width: vd.width + 'px' }).show(); - var after = documentViewportProperties.inspect(); - $('elementToViewportDimensions').hide(); - - documentViewportProperties.properties.each(function(prop) { - assert.equal(before[prop], after[prop], prop + ' was affected'); - }); - }); - - test('#getScrollOffsets', function (done) { - this.timeout(5000); - var original = document.viewport.getDimensions(); - - window.scrollTo(0, 0); - assert.equal(0, document.viewport.getScrollOffsets().top); - - window.scrollTo(0, 35); - assert.equal(35, document.viewport.getScrollOffsets().top); - - if (RESIZE_DISABLED) { - info("SKIPPING REMAINING TESTS (JavaScript window resizing disabled)"); - done(); - return; - } - - window.resizeTo(200, 650); - - wait(1000, done, function() { - var before = document.viewport.getDimensions(); - var delta = { width: 200 - before.width, height: 650 - before.height }; - - window.scrollTo(25, 35); - assert.equal(25, document.viewport.getScrollOffsets().left, - "NOTE: YOU MUST ALLOW JAVASCRIPT TO RESIZE YOUR WINDOW FOR THESE TESTS TO PASS"); - - wait(1000, done, function() { - // Restore original dimensions. - window.resizeTo( - original.width + delta.width, - original.height + delta.height - ); - done(); - }); - }); - }); - - }); // document.viewport - -}); diff --git a/test/unit/tests/number.test.js b/test/unit/tests/number.test.js deleted file mode 100644 index fe4042a4c..000000000 --- a/test/unit/tests/number.test.js +++ /dev/null @@ -1,41 +0,0 @@ - -suite('Number', function () { - this.name = 'number'; - - test('math methods', function () { - assert.equal(1, (0.9).round()); - assert.equal(-2, (-1.9).floor()); - assert.equal(-1, (-1.9).ceil()); - - $w('abs floor round ceil').each(function(method) { - assert.equal(Math[method](Math.PI), Math.PI[method]()); - }, this); - }); - - test('#toColorPart', function () { - assert.equal('00', (0).toColorPart()); - assert.equal('0a', (10).toColorPart()); - assert.equal('ff', (255).toColorPart()); - }); - - test('#toPaddedString', function () { - assert.equal('00', (0).toPaddedString(2, 16)); - assert.equal('0a', (10).toPaddedString(2, 16)); - assert.equal('ff', (255).toPaddedString(2, 16)); - assert.equal('000', (0).toPaddedString(3)); - assert.equal('010', (10).toPaddedString(3)); - assert.equal('100', (100).toPaddedString(3)); - assert.equal('1000', (1000).toPaddedString(3)); - }); - - test('#times', function () { - var results = []; - (5).times(function(i) { results.push(i); }); - assert.enumEqual($R(0, 4), results); - - results = []; - (5).times(function(i) { results.push(i * this.i); }, { i: 2 }); - assert.enumEqual([0, 2, 4, 6, 8], results); - }); - -}); diff --git a/test/unit/tests/object.test.js b/test/unit/tests/object.test.js deleted file mode 100644 index a32c53b9d..000000000 --- a/test/unit/tests/object.test.js +++ /dev/null @@ -1,231 +0,0 @@ -var Person = function(name){ - this.name = name; -}; - -Person.prototype.toJSON = function() { - return '-' + this.name; -}; - -/// - -suite('Object', function () { - this.name = 'object'; - - test('.extend', function () { - var object = {foo: 'foo', bar: [1, 2, 3]}; - assert.strictEqual(object, Object.extend(object)); - assert.hashEqual({foo: 'foo', bar: [1, 2, 3]}, object); - assert.strictEqual(object, Object.extend(object, {bla: 123})); - assert.hashEqual({foo: 'foo', bar: [1, 2, 3], bla: 123}, object); - assert.hashEqual({foo: 'foo', bar: [1, 2, 3], bla: null}, - Object.extend(object, {bla: null})); - }); - - test('.toQueryString', function () { - assert.equal('a=A&b=B&c=C&d=D%23', Object.toQueryString({a: 'A', b: 'B', c: 'C', d: 'D#'})); - }); - - test('.clone', function () { - var object = {foo: 'foo', bar: [1, 2, 3]}; - assert.notStrictEqual(object, Object.clone(object)); - assert.hashEqual(object, Object.clone(object)); - assert.hashEqual({}, Object.clone()); - var clone = Object.clone(object); - delete clone.bar; - assert.hashEqual({foo: 'foo'}, clone, - "Optimizing Object.clone perf using prototyping doesn't allow properties to be deleted."); - }); - - test('.keys', function () { - assert.enumEqual([], Object.keys({})); - assert.enumEqual(['bar', 'foo'], Object.keys({foo: 'foo', bar: 'bar'}).sort()); - function Foo() { this.bar = 'bar'; } - Foo.prototype.foo = 'foo'; - assert.enumEqual(['bar'], Object.keys(new Foo())); - assert.raise('TypeError', function(){ Object.keys(); }); - - var obj = { - foo: 'bar', - baz: 'thud', - toString: function() { return '1'; }, - valueOf: function() { return 1; } - }; - - assert.equal(4, Object.keys(obj).length, 'DontEnum properties should be included in Object.keys'); - }); - - test('.inspect', function () { - assert.equal('undefined', Object.inspect()); - assert.equal('undefined', Object.inspect(undefined)); - assert.equal('null', Object.inspect(null)); - assert.equal("'foo\\\\b\\\'ar'", Object.inspect('foo\\b\'ar')); - assert.equal('[]', Object.inspect([])); - assert.nothingRaised(function() { Object.inspect(window.Node); }); - }); - - test('.toJSON', function () { - assert.isUndefined(Object.toJSON(undefined)); - assert.isUndefined(Object.toJSON(Prototype.K)); - assert.equal('\"\"', Object.toJSON('')); - assert.equal('\"test\"', Object.toJSON('test')); - assert.equal('null', Object.toJSON(Number.NaN)); - assert.equal('0', Object.toJSON(0)); - assert.equal('-293', Object.toJSON(-293)); - assert.equal('[]', Object.toJSON([])); - assert.equal('[\"a\"]', Object.toJSON(['a'])); - assert.equal('[\"a\",1]', Object.toJSON(['a', 1])); - assert.equal('[\"a\",{\"b\":null}]', Object.toJSON(['a', {'b': null}])); - assert.equal('{\"a\":\"hello!\"}', Object.toJSON({a: 'hello!'})); - assert.equal('{}', Object.toJSON({})); - assert.equal('{}', Object.toJSON({a: undefined, b: undefined, c: Prototype.K})); - assert.equal('{\"b\":[null,false,true,null],\"c\":{\"a\":\"hello!\"}}', - Object.toJSON({'b': [undefined, false, true, undefined], c: {a: 'hello!'}})); - assert.equal('{\"b\":[null,false,true,null],\"c\":{\"a\":\"hello!\"}}', - Object.toJSON($H({'b': [undefined, false, true, undefined], c: {a: 'hello!'}}))); - assert.equal('true', Object.toJSON(true)); - assert.equal('false', Object.toJSON(false)); - assert.equal('null', Object.toJSON(null)); - var sam = new Person('sam'); - assert.equal('"-sam"', Object.toJSON(sam)); - }); - - test('.toHTML', function () { - assert.strictEqual('', Object.toHTML()); - assert.strictEqual('', Object.toHTML('')); - assert.strictEqual('', Object.toHTML(null)); - assert.strictEqual('0', Object.toHTML(0)); - assert.strictEqual('123', Object.toHTML(123)); - assert.equal('hello world', Object.toHTML('hello world')); - assert.equal('hello world', Object.toHTML({toHTML: function() { return 'hello world'; }})); - }); - - test('.isArray', function () { - assert(Object.isArray([])); - assert(Object.isArray([0])); - assert(Object.isArray([0, 1])); - assert(!Object.isArray({})); - assert(!Object.isArray($('object-test-list').childNodes)); - assert(!Object.isArray()); - assert(!Object.isArray('')); - assert(!Object.isArray('foo')); - assert(!Object.isArray(0)); - assert(!Object.isArray(1)); - assert(!Object.isArray(null)); - assert(!Object.isArray(true)); - assert(!Object.isArray(false)); - assert(!Object.isArray(undefined)); - }); - - test('.isHash', function () { - assert(Object.isHash($H())); - assert(Object.isHash(new Hash())); - assert(!Object.isHash({})); - assert(!Object.isHash(null)); - assert(!Object.isHash()); - assert(!Object.isHash('')); - assert(!Object.isHash(2)); - assert(!Object.isHash(false)); - assert(!Object.isHash(true)); - assert(!Object.isHash([])); - }); - - test('.isElement', function () { - assert(Object.isElement(document.createElement('div'))); - assert(Object.isElement(new Element('div'))); - assert(Object.isElement($('object-test'))); - assert(!Object.isElement(document.createTextNode('bla'))); - - // falsy variables should not mess up return value type - assert.strictEqual(false, Object.isElement(0)); - assert.strictEqual(false, Object.isElement('')); - assert.strictEqual(false, Object.isElement(NaN)); - assert.strictEqual(false, Object.isElement(null)); - assert.strictEqual(false, Object.isElement(undefined)); - }); - - test('.isFunction', function () { - assert(Object.isFunction(function() { })); - assert(Object.isFunction(Class.create())); - - assert(!Object.isFunction("a string")); - assert(!Object.isFunction($(document.createElement('div')))); - assert(!Object.isFunction([])); - assert(!Object.isFunction({})); - assert(!Object.isFunction(0)); - assert(!Object.isFunction(false)); - assert(!Object.isFunction(undefined)); - assert(!Object.isFunction(/xyz/), 'regular expressions are not functions'); - }); - - test('.isString', function () { - assert(!Object.isString(function() { })); - assert(Object.isString("a string")); - assert(Object.isString(new String("a string"))); - assert(!Object.isString(0)); - assert(!Object.isString([])); - assert(!Object.isString({})); - assert(!Object.isString(false)); - assert(!Object.isString(undefined)); - assert(!Object.isString(document), 'host objects should return false rather than throw exceptions'); - }); - - test('.isNumber', function () { - assert(Object.isNumber(0)); - assert(Object.isNumber(1.0)); - assert(Object.isNumber(new Number(0))); - assert(Object.isNumber(new Number(1.0))); - assert(!Object.isNumber(function() { })); - assert(!Object.isNumber({ test: function() { return 3; } })); - assert(!Object.isNumber("a string")); - assert(!Object.isNumber([])); - assert(!Object.isNumber({})); - assert(!Object.isNumber(false)); - assert(!Object.isNumber(undefined)); - assert(!Object.isNumber(document), 'host objects should return false rather than throw exceptions'); - }); - - test('.isDate', function () { - var d = new Date(); - assert(Object.isDate(d), 'constructor with no arguments'); - assert(Object.isDate(new Date(0)), 'constructor with milliseconds'); - assert(Object.isDate(new Date(1995, 11, 17)), 'constructor with Y, M, D'); - assert(Object.isDate(new Date(1995, 11, 17, 3, 24, 0)), 'constructor with Y, M, D, H, M, S'); - assert(Object.isDate(new Date(Date.parse("Dec 25, 1995"))), 'constructor with result of Date.parse'); - - assert(!Object.isDate(d.valueOf()), 'Date#valueOf returns a number'); - assert(!Object.isDate(function() { })); - assert(!Object.isDate(0)); - assert(!Object.isDate("a string")); - assert(!Object.isDate([])); - assert(!Object.isDate({})); - assert(!Object.isDate(false)); - assert(!Object.isDate(undefined)); - assert(!Object.isDate(document), 'host objects should return false rather than throw exceptions'); - }); - - test('.isUndefined', function () { - assert(Object.isUndefined(undefined)); - assert(!Object.isUndefined(null)); - assert(!Object.isUndefined(false)); - assert(!Object.isUndefined(0)); - assert(!Object.isUndefined("")); - assert(!Object.isUndefined(function() { })); - assert(!Object.isUndefined([])); - assert(!Object.isUndefined({})); - }); - - test('should not extend Object.prototype', function () { - // for-in is supported with objects - var iterations = 0, obj = { a: 1, b: 2, c: 3 }, property; - for (property in obj) iterations++; - assert.equal(3, iterations); - - // for-in is not supported with arrays - iterations = 0; - var arr = [1,2,3]; - for (property in arr) iterations++; - assert(iterations > 3); - }); - - -}); diff --git a/test/unit/tests/periodical_executer.test.js b/test/unit/tests/periodical_executer.test.js deleted file mode 100644 index 100e82a71..000000000 --- a/test/unit/tests/periodical_executer.test.js +++ /dev/null @@ -1,39 +0,0 @@ - -suite('PeriodicalExecuter', function () { - this.name = 'periodical_executer'; - - test('#stop', function (done) { - var peEventCount = 0; - function peEventFired(pe) { - if (++peEventCount > 2) pe.stop(); - } - - // peEventFired will stop the PeriodicalExecuter after 3 callbacks - new PeriodicalExecuter(peEventFired, 0.05); - - wait(600, done, function() { - assert.equal(3, peEventCount); - done(); - }); - }); - - test('#onTimerEvent', function () { - var pe = { - onTimerEvent: PeriodicalExecuter.prototype.onTimerEvent, - execute: function() { - assert(pe.currentlyExecuting); - } - }; - - pe.onTimerEvent(); - assert(!pe.currentlyExecuting); - - pe.execute = function() { - assert(pe.currentlyExecuting); - throw new Error(); - }; - assert.raise('Error', pe.onTimerEvent.bind(pe)); - assert(!pe.currentlyExecuting); - }); - -}); diff --git a/test/unit/tests/position.test.js b/test/unit/tests/position.test.js deleted file mode 100644 index fec9acd73..000000000 --- a/test/unit/tests/position.test.js +++ /dev/null @@ -1,47 +0,0 @@ - -suite('Position', function () { - this.name = 'position'; - - setup(function () { - scrollTo(0, 0); - Position.prepare(); - Position.includeScrollOffsets = false; - }); - - teardown(function () { - scrollTo(0, 0); - Position.prepare(); - Position.includeScrollOffsets = false; - }); - - test('.prepare', function () { - Position.prepare(); - assert.equal(0, Position.deltaX); - assert.equal(0, Position.deltaY); - scrollTo(20, 30); - Position.prepare(); - assert.equal(20, Position.deltaX); - assert.equal(30, Position.deltaY); - }); - - test('.within', function () { - [true, false].each(function(withScrollOffsets) { - Position.includeScrollOffsets = withScrollOffsets; - assert(!Position.within($('position_test_body_absolute'), 9, 9), 'outside left/top'); - assert(Position.within($('position_test_body_absolute'), 10, 10), 'left/top corner'); - assert(Position.within($('position_test_body_absolute'), 10, 19), 'left/bottom corner'); - assert(!Position.within($('position_test_body_absolute'), 10, 20), 'outside bottom'); - }, this); - - scrollTo(20, 30); - Position.prepare(); - Position.includeScrollOffsets = true; - assert(!Position.within($('position_test_body_absolute'), 9, 9), 'outside left/top'); - assert(Position.within($('position_test_body_absolute'), 10, 10), 'left/top corner'); - assert(Position.within($('position_test_body_absolute'), 10, 19), 'left/bottom corner'); - assert(!Position.within($('position_test_body_absolute'), 10, 20), 'outside bottom'); - }); - - - -}); diff --git a/test/unit/tests/prototype.test.js b/test/unit/tests/prototype.test.js deleted file mode 100644 index 52e4a6aec..000000000 --- a/test/unit/tests/prototype.test.js +++ /dev/null @@ -1,55 +0,0 @@ - -suite('Prototype', function () { - this.name = 'prototype'; - - test('browser detection', function () { - var results = $H(Prototype.Browser).map(function(engine){ - return engine; - }).partition(function(engine){ - return engine[1] === true; - }); - var trues = results[0], falses = results[1]; - - var ua = navigator.userAgent; - - info('User agent string is: ' + ua); - - // It's OK for there to be two true values if we're on MobileSafari, - // since it's also a WebKit browser. - if (Prototype.Browser.MobileSafari) { - assert(trues.size() === 2, 'MobileSafari should also identify as WebKit.'); - } else { - assert(trues.size() === 0 || trues.size() === 1, - 'There should be only one or no browser detected.'); - } - - // we should have definite trues or falses here - trues.each(function(result) { - assert(result[1] === true); - }, this); - falses.each(function(result) { - assert(result[1] === false); - }, this); - - if (ua.indexOf('AppleWebKit/') > -1) { - info('Running on WebKit'); - assert(Prototype.Browser.WebKit); - } - - if (!!window.opera) { - info('Running on Opera'); - assert(Prototype.Browser.Opera); - } - - if (ua.indexOf('MSIE') > -1 && !window.opera) { - info('Running on IE'); - assert(Prototype.Browser.IE); - } - - if (ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML') == -1) { - info('Running on Gecko'); - assert(Prototype.Browser.Gecko); - } - }); - -}); diff --git a/test/unit/tests/range.test.js b/test/unit/tests/range.test.js deleted file mode 100644 index ede02dd60..000000000 --- a/test/unit/tests/range.test.js +++ /dev/null @@ -1,67 +0,0 @@ - -suite('Range', function () { - this.name = 'range'; - - test('#include', function () { - assert(!$R(0, 0, true).include(0)); - assert($R(0, 0, false).include(0)); - - assert($R(0, 5, true).include(0)); - assert($R(0, 5, true).include(4)); - assert(!$R(0, 5, true).include(5)); - - assert($R(0, 5, false).include(0)); - assert($R(0, 5, false).include(5)); - assert(!$R(0, 5, false).include(6)); - }); - - test('#each', function () { - var results = []; - $R(0, 0, true).each(function(value) { - results.push(value); - }); - - assert.enumEqual([], results); - - results = []; - $R(0, 3, false).each(function(value) { - results.push(value); - }); - - assert.enumEqual([0, 1, 2, 3], results); - - results = []; - $R(2, 4, true).each(function(value, index) { - results.push(index); - }); - assert.enumEqual([0, 1], results); - }); - - test('#any', function () { - assert(!$R(1, 1, true).any()); - assert($R(0, 3, false).any(function(value) { - return value == 3; - })); - }); - - test('#all', function () { - assert($R(1, 1, true).all()); - assert($R(0, 3, false).all(function(value) { - return value <= 3; - })); - }); - - test('#toArray', function () { - assert.enumEqual([], $R(0, 0, true).toArray()); - assert.enumEqual([0], $R(0, 0, false).toArray()); - assert.enumEqual([0], $R(0, 1, true).toArray()); - assert.enumEqual([0, 1], $R(0, 1, false).toArray()); - assert.enumEqual([-3, -2, -1, 0, 1, 2], $R(-3, 3, true).toArray()); - assert.enumEqual([-3, -2, -1, 0, 1, 2, 3], $R(-3, 3, false).toArray()); - }); - - test('defaults to inclusive', function () { - assert.enumEqual($R(-3,3), $R(-3,3,false)); - }); - -}); diff --git a/test/unit/tests/regexp.test.js b/test/unit/tests/regexp.test.js deleted file mode 100644 index ae2d04856..000000000 --- a/test/unit/tests/regexp.test.js +++ /dev/null @@ -1,46 +0,0 @@ - -suite('RegExp', function () { - this.name = 'regexp'; - - test('#escape', function () { - assert.equal('word', RegExp.escape('word')); - assert.equal('\\/slashes\\/', RegExp.escape('/slashes/')); - assert.equal('\\\\backslashes\\\\', RegExp.escape('\\backslashes\\')); - assert.equal('\\\\border of word', RegExp.escape('\\border of word')); - - assert.equal('\\(\\?\\:non-capturing\\)', RegExp.escape('(?:non-capturing)')); - assert.equal('non-capturing', new RegExp(RegExp.escape('(?:') + '([^)]+)').exec('(?:non-capturing)')[1]); - - assert.equal('\\(\\?\\=positive-lookahead\\)', RegExp.escape('(?=positive-lookahead)')); - assert.equal('positive-lookahead', new RegExp(RegExp.escape('(?=') + '([^)]+)').exec('(?=positive-lookahead)')[1]); - - assert.equal('\\(\\?<\\=positive-lookbehind\\)', RegExp.escape('(?<=positive-lookbehind)')); - assert.equal('positive-lookbehind', new RegExp(RegExp.escape('(?<=') + '([^)]+)').exec('(?<=positive-lookbehind)')[1]); - - assert.equal('\\(\\?\\!negative-lookahead\\)', RegExp.escape('(?!negative-lookahead)')); - assert.equal('negative-lookahead', new RegExp(RegExp.escape('(?!') + '([^)]+)').exec('(?!negative-lookahead)')[1]); - - assert.equal('\\(\\?<\\!negative-lookbehind\\)', RegExp.escape('(?', new RegExp(RegExp.escape('
      ')).exec('
      ')[0]); - - assert.equal('false', RegExp.escape(false)); - assert.equal('undefined', RegExp.escape()); - assert.equal('null', RegExp.escape(null)); - assert.equal('42', RegExp.escape(42)); - - assert.equal('\\\\n\\\\r\\\\t', RegExp.escape('\\n\\r\\t')); - assert.equal('\n\r\t', RegExp.escape('\n\r\t')); - assert.equal('\\{5,2\\}', RegExp.escape('{5,2}')); - - assert.equal( - '\\/\\(\\[\\.\\*\\+\\?\\^\\=\\!\\:\\$\\{\\}\\(\\)\\|\\[\\\\\\]\\\\\\\/\\\\\\\\\\]\\)\\/g', - RegExp.escape('/([.*+?^=!:${}()|[\\]\\/\\\\])/g') - ); - }); - -}); diff --git a/test/unit/tests/selector.test.js b/test/unit/tests/selector.test.js deleted file mode 100644 index ce759ae5d..000000000 --- a/test/unit/tests/selector.test.js +++ /dev/null @@ -1,405 +0,0 @@ - -function reduce(arr) { - return arr.length > 1 ? arr : arr[0]; -} - - -suite('Selector', function () { - this.name = 'selector'; - - test('tag (div)', function () { - assert.enumEqual($A(document.getElementsByTagName('li')), $$('li')); - assert.enumEqual([$('strong')], $$('strong')); - assert.enumEqual([], $$('nonexistent')); - - var allNodes = $A(document.getElementsByTagName('*')).select( function(node) { - return node.tagName !== '!'; - }); - assert.enumEqual(allNodes, $$('*')); - }); - - test('ID (#some_id)', function () { - assert.enumEqual([$('fixtures')], $$('#fixtures')); - assert.enumEqual([], $$('#nonexistent')); - assert.enumEqual([$('troubleForm')], $$('#troubleForm')); - }); - - test('class (.some-class)', function () { - assert.enumEqual($('p', 'link_1', 'item_1'), $$('.first')); - assert.enumEqual([], $$('.second')); - }); - - test('tag + ID (div#some_id)', function () { - assert.enumEqual([$('strong')], $$('strong#strong')); - assert.enumEqual([], $$('p#strong')); - }); - - test('tag + class (div.some-class)', function () { - assert.enumEqual($('link_1', 'link_2'), $$('a.internal')); - assert.enumEqual([$('link_2')], $$('a.internal.highlight')); - assert.enumEqual([$('link_2')], $$('a.highlight.internal')); - assert.enumEqual([], $$('a.highlight.internal.nonexistent')); - }); - - test('id + class (#some_id.some-class)', function () { - assert.enumEqual([$('link_2')], $$('#link_2.internal')); - assert.enumEqual([$('link_2')], $$('.internal#link_2')); - assert.enumEqual([$('link_2')], $$('#link_2.internal.highlight')); - assert.enumEqual([], $$('#link_2.internal.nonexistent')); - }); - - test('tag + id + class (div#some_id.some-class)', function () { - assert.enumEqual([$('link_2')], $$('a#link_2.internal')); - assert.enumEqual([$('link_2')], $$('a.internal#link_2')); - assert.enumEqual([$('item_1')], $$('li#item_1.first')); - assert.enumEqual([], $$('li#item_1.nonexistent')); - assert.enumEqual([], $$('li#item_1.first.nonexistent')); - }); - - test('descendant combinator', function () { - assert.enumEqual($('em2', 'em', 'span'), $$('#fixtures a *')); - assert.enumEqual([$('p')], $$('div#fixtures p')); - }); - - test('combines results when multiple expressions are passed', function () { - assert.enumEqual( - $('link_1', 'link_2', 'item_1', 'item_2', 'item_3'), - $$('#p a', ' ul#list li ') - ); - }); - - test('tag + attr existence (a[href])', function () { - assert.enumEqual($$('#fixtures h1'), $$('h1[class]'), 'h1[class]'); - assert.enumEqual($$('#fixtures h1'), $$('h1[CLASS]'), 'h1[CLASS]'); - assert.enumEqual([$('item_3')], $$('li#item_3[class]'), 'li#item_3[class]'); - }); - - test('tag + attr equality (a[href="#"])', function () { - assert.enumEqual($('link_1', 'link_2', 'link_3'), $$('#fixtures a[href="#"]')); - assert.enumEqual($('link_1', 'link_2', 'link_3'), $$('#fixtures a[href=#]')); - }); - - test('tag + attr whitespace-tokenized (a[class~="internal"])', function () { - assert.enumEqual($('link_1', 'link_2'), $$('a[class~="internal"]'), "a[class~=\"internal\"]"); - assert.enumEqual($('link_1', 'link_2'), $$('a[class~=internal]'), "a[class~=internal]"); - }); - - test('attr ([href])', function () { - assert.enumEqual(document.body.select('a[href]'), document.body.select('[href]')); - assert.enumEqual($$('a[class~="internal"]'), $$('[class~=internal]')); - assert.enumEqual($$('*[id]'), $$('[id]')); - assert.enumEqual($('checked_radio', 'unchecked_radio'), $$('[type=radio]')); - assert.enumEqual($$('*[type=checkbox]'), $$('[type=checkbox]')); - assert.enumEqual($('with_title', 'commaParent'), $$('[title]')); - assert.enumEqual($$('#troubleForm *[type=radio]'), $$('#troubleForm [type=radio]')); - assert.enumEqual($$('#troubleForm *[type]'), $$('#troubleForm [type]')); - }); - - test('attr (with hyphen) ([foo-bar])', function () { - assert.enumEqual([$('attr_with_dash')], $$('[foo-bar]'), "attribute with hyphen"); - }); - - test('attr negation a[href!="#"]', function () { - assert.enumEqual($('item_2', 'item_3'), $$('#list li[id!="item_1"]')); - // assert.enumEqual([], $$('a[href!="#"]')); - }); - - test('attr (value with brackets) (input[name="brackets[5][]"])', function () { - assert.enumEqual( - $('chk_1', 'chk_2'), - $$('#troubleForm2 input[name="brackets[5][]"]') - ); - assert.enumEqual( - [$('chk_1')], - $$('#troubleForm2 input[name="brackets[5][]"]:checked') - ); - assert.enumEqual( - [$('chk_2')], - $$('#troubleForm2 input[name="brackets[5][]"][value=2]') - ); - try { - $$('#troubleForm2 input[name=brackets[5][]]'); - assert(false, 'Error not thrown'); - } catch (e) { - assert(true, 'Error thrown'); - } - }); - - test('attr (multiple) (div[style] p[id] strong)', function () { - assert.enumEqual([$('strong')], $$('div[style] p[id] strong'), 'div[style] p[id] strong'); - }); - - test('a (multiple) ([class~=external][href="#"])', function () { - assert.enumEqual([$('link_3')], $$('a[class~=external][href="#"]'), - 'a[class~=external][href="#"]'); - assert.enumEqual([], $$('a[class~=external][href!="#"]'), - 'a[class~=external][href!="#"]'); - }); - - test('.matchElements', function () { - assert.elementsMatch(Selector.matchElements($('list').descendants(), 'li'), '#item_1', '#item_2', '#item_3'); - assert.elementsMatch(Selector.matchElements($('fixtures').descendants(), 'a.internal'), '#link_1', '#link_2'); - assert.enumEqual([], Selector.matchElements($('fixtures').descendants(), 'p.last')); - assert.elementsMatch(Selector.matchElements($('fixtures').descendants(), '.inexistant, a.internal'), '#link_1', '#link_2'); - }); - - test('.findElement', function () { - assert.elementMatches(Selector.findElement($('list').descendants(), 'li'), 'li#item_1.first'); - assert.elementMatches(Selector.findElement($('list').descendants(), 'li', 1), 'li#item_2'); - assert.elementMatches(Selector.findElement($('list').descendants(), 'li#item_3'), 'li'); - assert.equal(undefined, Selector.findElement($('list').descendants(), 'em')); - }); - - test('Element#match', function () { - var span = $('dupL1'); - - // tests that should pass - assert(span.match('span')); - assert(span.match('span#dupL1')); - assert(span.match('div > span'), 'child combinator'); - assert(span.match('#dupContainer span'), 'descendant combinator'); - assert(span.match('#dupL1'), 'ID only'); - assert(span.match('span.span_foo'), 'class name 1'); - assert(span.match('span.span_bar'), 'class name 2'); - assert(span.match('span:first-child'), 'first-child pseudoclass'); - - assert(!span.match('span.span_wtf'), 'bogus class name'); - assert(!span.match('#dupL2'), 'different ID'); - assert(!span.match('div'), 'different tag name'); - assert(!span.match('span span'), 'different ancestry'); - assert(!span.match('span > span'), 'different parent'); - assert(!span.match('span:nth-child(5)'), 'different pseudoclass'); - - assert(!$('link_2').match('a[rel^=external]')); - assert($('link_1').match('a[rel^=external]')); - assert($('link_1').match('a[rel^="external"]')); - assert($('link_1').match("a[rel^='external']")); - - assert(span.match({ match: function(element) { return true; }}), 'custom selector'); - assert(!span.match({ match: function(element) { return false; }}), 'custom selector'); - }); - - test('attr (space in value) (cite[title="hello world!"])', function () { - assert.enumEqual([$('with_title')], $$('cite[title="hello world!"]')); - }); - - test('> combinator', function () { - assert.enumEqual($('link_1', 'link_2'), $$('p.first > a')); - assert.enumEqual($('father', 'uncle'), $$('div#grandfather > div')); - assert.enumEqual($('level2_1', 'level2_2'), $$('#level1>span')); - assert.enumEqual($('level2_1', 'level2_2'), $$('#level1 > span')); - assert.enumEqual($('level3_1', 'level3_2'), $$('#level2_1 > *')); - assert.enumEqual([], $$('div > #nonexistent')); - }); - - test('+ combinator', function () { - assert.enumEqual([$('uncle')], $$('div.brothers + div.brothers')); - assert.enumEqual([$('uncle')], $$('div.brothers + div')); - assert.equal($('level2_2'), reduce($$('#level2_1+span'))); - assert.equal($('level2_2'), reduce($$('#level2_1 + span'))); - assert.equal($('level2_2'), reduce($$('#level2_1 + *'))); - assert.enumEqual([], $$('#level2_2 + span')); - assert.equal($('level3_2'), reduce($$('#level3_1 + span'))); - assert.equal($('level3_2'), reduce($$('#level3_1 + *'))); - assert.enumEqual([], $$('#level3_2 + *')); - assert.enumEqual([], $$('#level3_1 + em')); - }); - - test('~ combinator', function () { - assert.enumEqual([$('list')], $$('#fixtures h1 ~ ul')); - assert.equal($('level2_2'), reduce($$('#level2_1 ~ span'))); - assert.enumEqual($('level2_2', 'level2_3'), reduce($$('#level2_1 ~ *'))); - assert.enumEqual([], $$('#level2_2 ~ span')); - assert.enumEqual([], $$('#level3_2 ~ *')); - assert.enumEqual([], $$('#level3_1 ~ em')); - assert.enumEqual([$('level3_2')], $$('#level3_1 ~ #level3_2')); - assert.enumEqual([$('level3_2')], $$('span ~ #level3_2')); - assert.enumEqual([], $$('div ~ #level3_2')); - assert.enumEqual([], $$('div ~ #level2_3')); - }); - - test('attr (weird operators)', function () { - assert.enumEqual($('father', 'uncle'), $$('div[class^=bro]'), 'matching beginning of string'); - assert.enumEqual($('father', 'uncle'), $$('div[class$=men]'), 'matching end of string'); - assert.enumEqual($('father', 'uncle'), $$('div[class*="ers m"]'), 'matching substring'); - assert.enumEqual($('level2_1', 'level2_2', 'level2_3'), $$('#level1 *[id^="level2_"]')); - assert.enumEqual($('level2_1', 'level2_2', 'level2_3'), $$('#level1 *[id^=level2_]')); - assert.enumEqual($('level2_1', 'level3_1'), $$('#level1 *[id$="_1"]')); - assert.enumEqual($('level2_1', 'level3_1'), $$('#level1 *[id$=_1]')); - assert.enumEqual($('level2_1', 'level3_2', 'level2_2', 'level2_3'), $$('#level1 *[id*="2"]')); - assert.enumEqual($('level2_1', 'level3_2', 'level2_2', 'level2_3'), $$('#level1 *[id*=2]')); - }); - - test('selectors with duplicates', function () { - assert.enumEqual($$('div div'), $$('div div').uniq()); - assert.enumEqual($('dupL2', 'dupL3', 'dupL4', 'dupL5'), $$('#dupContainer span span')); - }); - - test(':(first|last|only|nth|nth-last)-child', function () { - assert.enumEqual([$('level2_1')], $$('#level1>*:first-child')); - assert.enumEqual($('level2_1', 'level3_1', 'level_only_child'), $$('#level1 *:first-child')); - assert.enumEqual([$('level2_3')], $$('#level1>*:last-child')); - assert.enumEqual($('level3_2', 'level_only_child', 'level2_3'), $$('#level1 *:last-child')); - assert.enumEqual([$('level2_3')], $$('#level1>div:last-child')); - assert.enumEqual([$('level2_3')], $$('#level1 div:last-child')); - assert.enumEqual([], $$('#level1>div:first-child')); - assert.enumEqual([], $$('#level1>span:last-child')); - assert.enumEqual($('level2_1', 'level3_1'), $$('#level1 span:first-child')); - assert.enumEqual([], $$('#level1:first-child')); - assert.enumEqual([], $$('#level1>*:only-child')); - assert.enumEqual([$('level_only_child')], $$('#level1 *:only-child')); - assert.enumEqual([], $$('#level1:only-child')); - assert.enumEqual([$('link_2')], $$('#p *:nth-last-child(2)'), 'nth-last-child'); - assert.enumEqual([$('link_2')], $$('#p *:nth-child(3)'), 'nth-child'); - assert.enumEqual([$('link_2')], $$('#p a:nth-child(3)'), 'nth-child'); - assert.enumEqual($('item_2', 'item_3'), $$('#list > li:nth-child(n+2)')); - assert.enumEqual($('item_1', 'item_2'), $$('#list > li:nth-child(-n+2)')); - }); - - test(':(first|last|nth|nth-last)-of-type', function () { - assert.enumEqual([$('link_2')], $$('#p a:nth-of-type(2)'), 'nth-of-type'); - assert.enumEqual([$('link_1')], $$('#p a:nth-of-type(1)'), 'nth-of-type'); - assert.enumEqual([$('link_2')], $$('#p a:nth-last-of-type(1)'), 'nth-last-of-type'); - assert.enumEqual([$('link_1')], $$('#p a:first-of-type'), 'first-of-type'); - assert.enumEqual([$('link_2')], $$('#p a:last-of-type'), 'last-of-type'); - }); - - test(':not', function () { - assert.enumEqual([$('link_2')], $$('#p a:not(a:first-of-type)'), 'first-of-type'); - assert.enumEqual([$('link_1')], $$('#p a:not(a:last-of-type)'), 'last-of-type'); - assert.enumEqual([$('link_2')], $$('#p a:not(a:nth-of-type(1))'), 'nth-of-type'); - assert.enumEqual([$('link_1')], $$('#p a:not(a:nth-last-of-type(1))'), 'nth-last-of-type'); - assert.enumEqual([$('link_2')], $$('#p a:not([rel~=nofollow])'), 'attribute 1'); - assert.enumEqual([$('link_2')], $$('#p a:not(a[rel^=external])'), 'attribute 2'); - assert.enumEqual([$('link_2')], $$('#p a:not(a[rel$=nofollow])'), 'attribute 3'); - assert.enumEqual([$('em')], $$('#p a:not(a[rel$="nofollow"]) > em'), 'attribute 4'); - assert.enumEqual([$('item_2')], $$('#list li:not(#item_1):not(#item_3)'), 'adjacent :not clauses'); - assert.enumEqual([$('son')], $$('#grandfather > div:not(#uncle) #son')); - assert.enumEqual([$('em')], $$('#p a:not(a[rel$="nofollow"]) em'), 'attribute 4 + all descendants'); - assert.enumEqual([$('em')], $$('#p a:not(a[rel$="nofollow"])>em'), 'attribute 4 (without whitespace)'); - }); - - test(':enabled, :disabled, :checked', function () { - assert.enumEqual( - [$('disabled_text_field')], - $$('#troubleForm > *:disabled'), - ':disabled' - ); - assert.enumEqual( - $('troubleForm').getInputs().without($('disabled_text_field')), - $$('#troubleForm > *:enabled'), - ':enabled' - ); - assert.enumEqual( - $('checked_box', 'checked_radio'), - $$('#troubleForm *:checked'), - ':checked' - ); - }); - - test('identical results from equivalent selectors', function () { - assert.enumEqual($$('div.brothers'), $$('div[class~=brothers]')); - assert.enumEqual($$('div.brothers'), $$('div[class~=brothers].brothers')); - assert.enumEqual($$('div:not(.brothers)'), $$('div:not([class~=brothers])')); - assert.enumEqual($$('li ~ li'), $$('li:not(:first-child)')); - assert.enumEqual($$('ul > li'), $$('ul > li:nth-child(n)')); - assert.enumEqual($$('ul > li:nth-child(even)'), $$('ul > li:nth-child(2n)')); - assert.enumEqual($$('ul > li:nth-child(odd)'), $$('ul > li:nth-child(2n+1)')); - assert.enumEqual($$('ul > li:first-child'), $$('ul > li:nth-child(1)')); - assert.enumEqual($$('ul > li:last-child'), $$('ul > li:nth-last-child(1)')); - assert.enumEqual($$('ul > li:nth-child(n-999)'), $$('ul > li')); - assert.enumEqual($$('ul>li'), $$('ul > li')); - assert.enumEqual($$('#p a:not(a[rel$="nofollow"])>em'), $$('#p a:not(a[rel$="nofollow"]) > em')); - }); - - test('selectors that should return nothing', function () { - assert.enumEqual([], $$('span:empty > *')); - assert.enumEqual([], $$('div.brothers:not(.brothers)')); - assert.enumEqual([], $$('#level2_2 :only-child:not(:last-child)')); - assert.enumEqual([], $$('#level2_2 :only-child:not(:first-child)')); - }); - - test('$$ (separates selectors properly)', function () { - assert.enumEqual($('p', 'link_1', 'list', 'item_1', 'item_3', 'troubleForm'), $$('#list, .first,#item_3 , #troubleForm')); - assert.enumEqual($('p', 'link_1', 'list', 'item_1', 'item_3', 'troubleForm'), $$('#list, .first', '#item_3 , #troubleForm')); - assert.enumEqual($('commaParent', 'commaChild'), $$('form[title*="commas,"], input[value="#commaOne,#commaTwo"]')); - assert.enumEqual($('commaParent', 'commaChild'), $$('form[title*="commas,"]', 'input[value="#commaOne,#commaTwo"]')); - }); - - test('$$ (extends all nodes)', function () { - var element = document.createElement('div'); - (3).times(function(){ - element.appendChild(document.createElement('div')); - }); - element.setAttribute('id', 'scratch_element'); - $$('body')[0].appendChild(element); - - var results = $$('#scratch_element div'); - assert(typeof results[0].show == 'function'); - assert(typeof results[1].show == 'function'); - assert(typeof results[2].show == 'function'); - }); - - test('copied nodes get included', function () { - assert.elementsMatch( - Selector.matchElements($('counted_container').descendants(), 'div'), - 'div.is_counted' - ); - $('counted_container').innerHTML += $('counted_container').innerHTML; - assert.elementsMatch( - Selector.matchElements($('counted_container').descendants(), 'div'), 'div.is_counted', - 'div.is_counted' - ); - }); - - test('#select (on detached nodes)', function () { - var wrapper = new Element("div"); - wrapper.update("
      "); - assert.isNotNullOrUndefined(wrapper.select('[id=myTD]')[0], - 'selecting: [id=myTD]'); - assert.isNotNullOrUndefined(wrapper.select('#myTD')[0], - 'selecting: #myTD'); - assert.isNotNullOrUndefined(wrapper.select('td')[0], - 'selecting: td'); - assert($$('#myTD').length == 0, - 'should not turn up in document-rooted search'); - }); - - test('#down', function () { - var a = $('dupL4'); - var b = $('dupContainer').down('#dupL4'); - - assert.equal(a, b); - }); - - test('#down (with dot and colon)', function () { - var a = $('dupL4_dotcolon'); - var b = $('dupContainer.withdot:active').down('#dupL4_dotcolon'); - var c = $('dupContainer.withdot:active').select('#dupL4_dotcolon'); - - assert.equal(a, b); - assert.enumEqual([a], c); - }); - - test('descendant selector bugs', function () { - var el = document.createElement('div'); - el.innerHTML = '
      '; - document.body.appendChild(el); - assert.equal(2, $(el).select('ul li').length); - document.body.removeChild(el); - }); - - test('.findElement (with index when elements are not in document order)', function () { - var ancestors = $("target_1").ancestors(); - assert.equal( - $("container_2"), - Selector.findElement(ancestors, "[container], .container", 0) - ); - assert.equal( - $("container_1"), - Selector.findElement(ancestors, "[container], .container", 1) - ); - }); - - -}); diff --git a/test/unit/tests/selector_engine.test.js b/test/unit/tests/selector_engine.test.js deleted file mode 100644 index 7c6d36035..000000000 --- a/test/unit/tests/selector_engine.test.js +++ /dev/null @@ -1,47 +0,0 @@ - -suite('Selector engine', function () { - this.name = 'selector_engine'; - - test('.engine', function () { - assert(Prototype.Selector.engine); - }); - - test('.select', function () { - var elements = Prototype.Selector.select('.test_class'); - - assert(Object.isArray(elements)); - assert.equal(2, elements.length); - assert.equal('div_parent', elements[0].id); - assert.equal('div_child', elements[1].id); - }); - - test('.select (with context)', function () { - var elements = Prototype.Selector.select('.test_class', $('div_parent')); - - assert(Object.isArray(elements)); - assert.equal(1, elements.length); - assert.equal('div_child', elements[0].id); - }); - - test('.select (with empty result set)', function () { - var elements = Prototype.Selector.select('.non_existent'); - - assert(Object.isArray(elements)); - assert.equal(0, elements.length); - }); - - test('.match', function () { - var element = $('div_parent'); - - assert.equal(true, Prototype.Selector.match(element, '.test_class')); - assert.equal(false, Prototype.Selector.match(element, '.non_existent')); - }); - - test('.find', function () { - var elements = document.getElementsByTagName('*'), - expression = '.test_class'; - assert.equal('div_parent', Prototype.Selector.find(elements, expression).id); - assert.equal('div_child', Prototype.Selector.find(elements, expression, 1).id); - }); - -}); diff --git a/test/unit/tests/string.test.js b/test/unit/tests/string.test.js deleted file mode 100644 index 27ef2b696..000000000 --- a/test/unit/tests/string.test.js +++ /dev/null @@ -1,597 +0,0 @@ -var attackTarget; -var evalScriptsCounter = 0, - largeTextEscaped = '<span>test</span>', - largeTextUnescaped = 'test'; -(2048).times(function(){ - largeTextEscaped += ' ABC'; - largeTextUnescaped += ' ABC'; -}); - - -/// - -suite('String', function () { - this.name = 'string'; - - test('.interpret', function () { - assert.strictEqual('true', String.interpret(true)); - assert.strictEqual('123', String.interpret(123)); - assert.strictEqual('foo bar', String.interpret('foo bar')); - assert.strictEqual( - 'object string', - String.interpret({ toString: function (){ return 'object string'; } }) - ); - assert.strictEqual('0', String.interpret(0)); - assert.strictEqual('false', String.interpret(false)); - assert.strictEqual('', String.interpret(undefined)); - assert.strictEqual('', String.interpret(null)); - assert.strictEqual('', String.interpret('')); - }); - - test('#gsub (with replacement function)', function () { - var source = 'foo boo boz'; - - assert.equal('Foo Boo BoZ', - source.gsub(/[^o]+/, function(match) { - return match[0].toUpperCase(); - })); - assert.equal('f2 b2 b1z', - source.gsub(/o+/, function(match) { - return match[0].length; - })); - assert.equal('f0 b0 b1z', - source.gsub(/o+/, function(match) { - return match[0].length % 2; - })); - }); - - test('#gsub (with replacement string)', function () { - var source = 'foo boo boz'; - - assert.equal('foobooboz', - source.gsub(/\s+/, '')); - assert.equal(' z', - source.gsub(/(.)(o+)/, '')); - - assert.equal('ウィメンズ2007
      クルーズコレクション', - 'ウィメンズ2007\nクルーズコレクション'.gsub(/\n/,'
      ')); - assert.equal('ウィメンズ2007
      クルーズコレクション', - 'ウィメンズ2007\nクルーズコレクション'.gsub('\n','
      ')); - - assert.equal('barfbarobarobar barbbarobarobar barbbarobarzbar', - source.gsub('', 'bar')); - assert.equal('barfbarobarobar barbbarobarobar barbbarobarzbar', - source.gsub(new RegExp(''), 'bar')); - }); - - test('#gsub (with replacement template string)', function () { - var source = 'foo boo boz'; - - assert.equal('-oo-#{1}- -oo-#{1}- -o-#{1}-z', - source.gsub(/(.)(o+)/, '-#{2}-\\#{1}-')); - assert.equal('-foo-f- -boo-b- -bo-b-z', - source.gsub(/(.)(o+)/, '-#{0}-#{1}-')); - assert.equal('-oo-f- -oo-b- -o-b-z', - source.gsub(/(.)(o+)/, '-#{2}-#{1}-')); - assert.equal(' z', - source.gsub(/(.)(o+)/, '#{3}')); - }); - - test('#gsub (with troublesome characters)', function () { - assert.equal('ab', 'a|b'.gsub('|', '')); - assert.equal('ab', 'ab(?:)'.gsub('(?:)', '')); - assert.equal('ab', 'ab()'.gsub('()', '')); - assert.equal('ab', 'ab'.gsub('^', '')); - assert.equal('ab', 'a?b'.gsub('?', '')); - assert.equal('ab', 'a+b'.gsub('+', '')); - assert.equal('ab', 'a*b'.gsub('*', '')); - assert.equal('ab', 'a{1}b'.gsub('{1}', '')); - assert.equal('ab', 'a.b'.gsub('.', '')); - }); - - test('#gsub (with zero-length match)', function () { - assert.equal('ab', 'ab'.gsub('', '')); - assert.equal('a', 'a'.gsub(/b*/, 'c')); - assert.equal('abc', 'abc'.gsub(/b{0}/, '')); - }); - - test('#sub (with replacement function)', function () { - var source = 'foo boo boz'; - - assert.equal('Foo boo boz', - source.sub(/[^o]+/, function(match) { - return match[0].toUpperCase(); - }), 1); - assert.equal('Foo Boo boz', - source.sub(/[^o]+/, function(match) { - return match[0].toUpperCase(); - }, 2), 2); - assert.equal(source, - source.sub(/[^o]+/, function(match) { - return match[0].toUpperCase(); - }, 0), 0); - assert.equal(source, - source.sub(/[^o]+/, function(match) { - return match[0].toUpperCase(); - }, -1), -1); - }); - - test('#sub (with replacement string)', function () { - var source = 'foo boo boz'; - - assert.equal('oo boo boz', - source.sub(/[^o]+/, '')); - assert.equal('oooo boz', - source.sub(/[^o]+/, '', 2)); - assert.equal('-f-oo boo boz', - source.sub(/[^o]+/, '-#{0}-')); - assert.equal('-f-oo- b-oo boz', - source.sub(/[^o]+/, '-#{0}-', 2)); - }); - - test('#scan', function () { - var source = 'foo boo boz', results = []; - var str = source.scan(/[o]+/, function(match) { - results.push(match[0].length); - }); - assert.enumEqual([2, 2, 1], results); - assert.equal(source, source.scan(/x/, function () { - assert(false, 'this iterator should never get called'); - })); - assert(typeof str == 'string'); - }); - - test('#toArray', function () { - assert.enumEqual([],''.toArray()); - assert.enumEqual(['a'],'a'.toArray()); - assert.enumEqual(['a','b'],'ab'.toArray()); - assert.enumEqual(['f','o','o'],'foo'.toArray()); - }); - - test('#camelize', function () { - assert.equal('', ''.camelize()); - assert.equal('', '-'.camelize()); - assert.equal('foo', 'foo'.camelize()); - assert.equal('foo_bar', 'foo_bar'.camelize()); - assert.equal('FooBar', '-foo-bar'.camelize()); - assert.equal('FooBar', 'FooBar'.camelize()); - - assert.equal('fooBar', 'foo-bar'.camelize()); - assert.equal('borderBottomWidth', 'border-bottom-width'.camelize()); - - assert.equal('classNameTest','class-name-test'.camelize()); - assert.equal('classNameTest','className-test'.camelize()); - assert.equal('classNameTest','class-nameTest'.camelize()); - }); - - test('#capitalize', function () { - assert.equal('',''.capitalize()); - assert.equal('Ä','ä'.capitalize()); - assert.equal('A','A'.capitalize()); - assert.equal('Hello','hello'.capitalize()); - assert.equal('Hello','HELLO'.capitalize()); - assert.equal('Hello','Hello'.capitalize()); - assert.equal('Hello world','hello WORLD'.capitalize()); - }); - - test('#underscore', function () { - assert.equal('', ''.underscore()); - assert.equal('_', '-'.underscore()); - assert.equal('foo', 'foo'.underscore()); - assert.equal('foo', 'Foo'.underscore()); - assert.equal('foo_bar', 'foo_bar'.underscore()); - assert.equal('border_bottom', 'borderBottom'.underscore()); - assert.equal('border_bottom_width', 'borderBottomWidth'.underscore()); - assert.equal('border_bottom_width', 'border-Bottom-Width'.underscore()); }); - - test('#dasherize', function () { - assert.equal('', ''.dasherize()); - assert.equal('foo', 'foo'.dasherize()); - assert.equal('Foo', 'Foo'.dasherize()); - assert.equal('foo-bar', 'foo-bar'.dasherize()); - assert.equal('border-bottom-width', 'border_bottom_width'.dasherize()); - }); - - test('#truncate', function () { - var source = 'foo boo boz foo boo boz foo boo boz foo boo boz'; - assert.equal(source, source.truncate(source.length)); - assert.equal('foo boo boz foo boo boz foo...', source.truncate(0)); - assert.equal('fo...', source.truncate(5)); - assert.equal('foo b', source.truncate(5, '')); - - assert(typeof 'foo'.truncate(5) == 'string'); - assert(typeof 'foo bar baz'.truncate(5) == 'string'); - }); - - test('#strip', function () { - assert.equal('hello world', ' hello world '.strip()); - assert.equal('hello world', 'hello world'.strip()); - assert.equal('hello \n world', ' hello \n world '.strip()); - assert.equal('', ' '.strip()); - }); - - test('#stripTags', function () { - assert.equal('hello world', 'hello world'.stripTags()); - assert.equal('hello world', 'hello world'.stripTags()); - assert.equal('hello world', 'hello world'.stripTags()); - assert.equal('hello world', 'hello world'.stripTags()); - assert.equal('1\n2', '1\n2'.stripTags()); - assert.equal('one < two blah baz', 'one < two blah baz'.stripTags()); - assert.equal('hello world abc', 'hello world
      abc'.stripTags()); - assert.equal('hello world abc', 'hello world
      abc'.stripTags()); - assert.equal('hello world abc', 'hello

      world



      abc'.stripTags()); - }); - - test('#stripScripts', function () { - assert.equal('foo bar', 'foo bar'.stripScripts()); - assert.equal('foo bar', ('foo - - - - - - - - - <% @suites.each do |suite| %> - - <% end %> - - - - - - - -
      - -
      - -
      - <%= yield %> -
      - - - - - - - - - \ No newline at end of file diff --git a/test/unit/views/tests.erb b/test/unit/views/tests.erb deleted file mode 100644 index d2814f8f9..000000000 --- a/test/unit/views/tests.erb +++ /dev/null @@ -1,9 +0,0 @@ - - -<% @suites.each do |suite| %> - <% if suite_has_html?(suite) %> -
      - <%= erb(:"tests/#{suite}", :locals => { :name => suite }) %> -
      - <% end %> -<% end %> \ No newline at end of file diff --git a/test/unit/views/tests/ajax.erb b/test/unit/views/tests/ajax.erb deleted file mode 100644 index 4af5e267a..000000000 --- a/test/unit/views/tests/ajax.erb +++ /dev/null @@ -1,2 +0,0 @@ -
      -
      diff --git a/test/unit/views/tests/array.erb b/test/unit/views/tests/array.erb deleted file mode 100644 index 8f091878c..000000000 --- a/test/unit/views/tests/array.erb +++ /dev/null @@ -1 +0,0 @@ -
      22
      diff --git a/test/unit/views/tests/dom.erb b/test/unit/views/tests/dom.erb deleted file mode 100644 index e7c694e9f..000000000 --- a/test/unit/views/tests/dom.erb +++ /dev/null @@ -1,377 +0,0 @@ - - -
      -

      Scroll test

      -
      - - - -
      visible
      - -
      hidden
      -
      visible
      - -
      visible
      - -
      visible
      - -
      - -
      - - - - - - - - - - - - -
      Data
      First Row
      Second Row
      -
      - -
      - - - - - - - - - - - - -
      Data
      First Row
      Second Row
      -
      - -

      Test paragraph outside of container

      - -
      -

      Test paragraph 1 inside of container

      -

      Test paragraph 2 inside of container

      -

      Test paragraph 3 inside of container

      -

      Test paragraph 4 inside of container

      -
      - -
      to be updated
      -
      -
      -
      -
      -
      -
      -
      -
      -
      -
      - -

      some text

      some text

      - -
      V
      -
      H
      -
      S
      - -
      - -
      - -
      - - -
      -
      - - - - -
      -

      -
        -
      • -
      • -
      • -
      -
      -
      -
      - - -
      - -
      blah
      -blah -blah - -
      -
      -
      -
      - -
      test_csstext_1
      -
      test_csstext_2
      -
      test_csstext_3
      -
      test_csstext_4
      -
      test_csstext_5
      - -
      -
      -
      -
      - -
      - - - -
      - - - - - -
      - - -

      - -
      - - - - - -
      - - - - - -
      AB
      C
      DEF
      - -
      -
      - -
      -
      - -
      NFN
      -
      NFI
      -
      NFS
      - -
      FI
      -
      FS
      - -op2 -op2 -op3 -op3 -
      -
      -
      -
      -
      -
      - - - - - - -
      Data
      - -
      - -
      - - -

      -

      - - -

      -

      content

      -
      -
      -
      -
      -
      -
      -
      -
      - -

      some content.

      -

      some content.

      -

      some content.

      -

      some content.

      -
      -
      -
      - - - -
      -

      - - -
      -
      -
      -
      testtest
      -
      XYZ
      -
      -
      - foo - bar -
      -
      -
      - -
      -
      -
      -
      -
      -
      -
      -
      - - -
      \ No newline at end of file diff --git a/test/unit/views/tests/element_mixins.erb b/test/unit/views/tests/element_mixins.erb deleted file mode 100644 index 583d0e5f3..000000000 --- a/test/unit/views/tests/element_mixins.erb +++ /dev/null @@ -1,4 +0,0 @@ -
      - - -
      \ No newline at end of file diff --git a/test/unit/views/tests/enumerable.erb b/test/unit/views/tests/enumerable.erb deleted file mode 100644 index 5e7e8f3b3..000000000 --- a/test/unit/views/tests/enumerable.erb +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - -
      diff --git a/test/unit/views/tests/event.erb b/test/unit/views/tests/event.erb deleted file mode 100644 index 2c33b123c..000000000 --- a/test/unit/views/tests/event.erb +++ /dev/null @@ -1,4 +0,0 @@ - -
      diff --git a/test/unit/views/tests/event_handler.erb b/test/unit/views/tests/event_handler.erb deleted file mode 100644 index c103f6415..000000000 --- a/test/unit/views/tests/event_handler.erb +++ /dev/null @@ -1,4 +0,0 @@ - diff --git a/test/unit/views/tests/form.erb b/test/unit/views/tests/form.erb deleted file mode 100644 index a43ea300b..000000000 --- a/test/unit/views/tests/form.erb +++ /dev/null @@ -1,148 +0,0 @@ -
      -
      - -
      This is not a form element
      - - - - -
      - -
      -
      - - - - - -
      - - -
      - - - - - -
      - - -
      - - - - -
      - - - -
      -
      - -
      - - - - - -
      This is not a form element
      - - - - -
      -
      - - - -
      - -
      - -
      - - -
      -
      -

      - - -
      - -
      -

      - - - -
      - -
      -

      - - - -
      - -
      - - - - - -
      - - -
      - -
      - - - - - -
      -
      diff --git a/test/unit/views/tests/layout.erb b/test/unit/views/tests/layout.erb deleted file mode 100644 index b07949786..000000000 --- a/test/unit/views/tests/layout.erb +++ /dev/null @@ -1,380 +0,0 @@ -
      -

      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

      -
      - - - - - -
      -

      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

      -
      - - - - - -
      -

      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

      -
      - - - - -
      -
      - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -
      -
      - - - - -
      -
      -
      - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. -
      -
      -
      - - - - -
      -
      -
      - Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. -
      -
      -
      - - - - -
      -
      - Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -
      -
      - - - - - -
      -
      - Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. -
      -
      - - - - -
      -
      - Duis aute. -
      -
      - - - - -
      - Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. -
      - - - - -
      -

      Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

      -
      - - - -
      V
      -
      H
      -
      S
      - -
      -
      -
      -
      -
      -
      - - - - - - -
      Data
      - -
      - -
      - - - - - -
      -
      -
      -
      testtest
      -
      XYZ
      -
      -
      - foo - bar -
      -
      -
      - - -
      - - - - - - - -
      Force scroll
      - - - - - - - - - - - -
      -
      source
      -
      - -
      -
      target
      -
      - - \ No newline at end of file diff --git a/test/unit/views/tests/object.erb b/test/unit/views/tests/object.erb deleted file mode 100644 index c2a7a0f3e..000000000 --- a/test/unit/views/tests/object.erb +++ /dev/null @@ -1,6 +0,0 @@ -
      -
        -
      • -
      • -
      • -
      \ No newline at end of file diff --git a/test/unit/views/tests/position.erb b/test/unit/views/tests/position.erb deleted file mode 100644 index 803b7f550..000000000 --- a/test/unit/views/tests/position.erb +++ /dev/null @@ -1,9 +0,0 @@ -
      - -
      -
      -
      -
      testtest
      -
      -
      -
      diff --git a/test/unit/views/tests/selector.erb b/test/unit/views/tests/selector.erb deleted file mode 100644 index 4a47a1db7..000000000 --- a/test/unit/views/tests/selector.erb +++ /dev/null @@ -1,88 +0,0 @@ - diff --git a/test/unit/views/tests/selector_engine.erb b/test/unit/views/tests/selector_engine.erb deleted file mode 100644 index 4e8c2079b..000000000 --- a/test/unit/views/tests/selector_engine.erb +++ /dev/null @@ -1,4 +0,0 @@ -
      -
      -
      -
      \ No newline at end of file diff --git a/vendor/caja_builder b/vendor/caja_builder deleted file mode 160000 index aeda517c2..000000000 --- a/vendor/caja_builder +++ /dev/null @@ -1 +0,0 @@ -Subproject commit aeda517c2e82db92bc88d56ed68fa4ce05f487a9 diff --git a/vendor/legacy_selector/repository/legacy_selector.js b/vendor/legacy_selector/repository/legacy_selector.js deleted file mode 100644 index 288b7571c..000000000 --- a/vendor/legacy_selector/repository/legacy_selector.js +++ /dev/null @@ -1,723 +0,0 @@ -/* Portions of the Prototype.LegacySelector class are derived from Jack Slocum's DomQuery, - * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style - * license. Please see http://www.yui-ext.com/ for more information. */ - -Prototype.LegacySelector = Class.create({ - initialize: function(expression) { - this.expression = expression.strip(); - - if (this.shouldUseSelectorsAPI()) { - this.mode = 'selectorsAPI'; - } else { - this.mode = "normal"; - this.compileMatcher(); - } - }, - - shouldUseSelectorsAPI: function() { - if (!Prototype.BrowserFeatures.SelectorsAPI) return false; - - if (!Prototype.LegacySelector._div) Prototype.LegacySelector._div = new Element('div'); - - // Make sure the browser treats the selector as valid. Test on an - // isolated element to minimize cost of this check. - try { - Prototype.LegacySelector._div.querySelector(this.expression); - } catch(e) { - return false; - } - - return true; - }, - - compileMatcher: function() { - var e = this.expression, ps = Prototype.LegacySelector.patterns, h = Prototype.LegacySelector.handlers, - c = Prototype.LegacySelector.criteria, le, p, m, len = ps.length, name; - - if (Prototype.LegacySelector._cache[e]) { - this.matcher = Prototype.LegacySelector._cache[e]; - return; - } - - this.matcher = ["this.matcher = function(root) {", - "var r = root, h = Prototype.LegacySelector.handlers, c = false, n;"]; - - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i = 0; i"; - } -}); - -Prototype.LegacySelector.CASE_INSENSITIVE_CLASS_NAMES = false; - -Object.extend(Prototype.LegacySelector, { - _cache: { }, - - xpath: { - descendant: "//*", - child: "/*", - adjacent: "/following-sibling::*[1]", - laterSibling: '/following-sibling::*', - tagName: function(m) { - if (m[1] == '*') return ''; - return "[local-name()='" + m[1].toLowerCase() + - "' or local-name()='" + m[1].toUpperCase() + "']"; - }, - className: "[contains(concat(' ', @class, ' '), ' #{1} ')]", - id: "[@id='#{1}']", - attrPresence: function(m) { - m[1] = m[1].toLowerCase(); - return new Template("[@#{1}]").evaluate(m); - }, - attr: function(m) { - m[1] = m[1].toLowerCase(); - m[3] = m[5] || m[6]; - return new Template(Prototype.LegacySelector.xpath.operators[m[2]]).evaluate(m); - }, - pseudo: function(m) { - var h = Prototype.LegacySelector.xpath.pseudos[m[1]]; - if (!h) return ''; - if (Object.isFunction(h)) return h(m); - return new Template(Prototype.LegacySelector.xpath.pseudos[m[1]]).evaluate(m); - }, - operators: { - '=': "[@#{1}='#{3}']", - '!=': "[@#{1}!='#{3}']", - '^=': "[starts-with(@#{1}, '#{3}')]", - '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']", - '*=': "[contains(@#{1}, '#{3}')]", - '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]", - '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]" - }, - pseudos: { - 'first-child': '[not(preceding-sibling::*)]', - 'last-child': '[not(following-sibling::*)]', - 'only-child': '[not(preceding-sibling::* or following-sibling::*)]', - 'empty': "[count(*) = 0 and (count(text()) = 0)]", - 'checked': "[@checked]", - 'disabled': "[(@disabled) and (@type!='hidden')]", - 'enabled': "[not(@disabled) and (@type!='hidden')]", - 'not': function(m) { - var e = m[6], p = Prototype.LegacySelector.patterns, - x = Prototype.LegacySelector.xpath, le, v, len = p.length, name; - - var exclusion = []; - while (e && le != e && (/\S/).test(e)) { - le = e; - for (var i = 0; i= 0)]"; - return new Template(predicate).evaluate({ - fragment: fragment, a: a, b: b }); - } - } - } - }, - - criteria: { - tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;', - className: 'n = h.className(n, r, "#{1}", c); c = false;', - id: 'n = h.id(n, r, "#{1}", c); c = false;', - attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;', - attr: function(m) { - m[3] = (m[5] || m[6]); - return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m); - }, - pseudo: function(m) { - if (m[6]) m[6] = m[6].replace(/"/g, '\\"'); - return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m); - }, - descendant: 'c = "descendant";', - child: 'c = "child";', - adjacent: 'c = "adjacent";', - laterSibling: 'c = "laterSibling";' - }, - - patterns: [ - // combinators must be listed first - // (and descendant needs to be last combinator) - { name: 'laterSibling', re: /^\s*~\s*/ }, - { name: 'child', re: /^\s*>\s*/ }, - { name: 'adjacent', re: /^\s*\+\s*/ }, - { name: 'descendant', re: /^\s/ }, - - // selectors follow - { name: 'tagName', re: /^\s*(\*|[\w\-]+)(\b|$)?/ }, - { name: 'id', re: /^#([\w\-\*]+)(\b|$)/ }, - { name: 'className', re: /^\.([\w\-\*]+)(\b|$)/ }, - { name: 'pseudo', re: /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/ }, - { name: 'attrPresence', re: /^\[((?:[\w-]+:)?[\w-]+)\]/ }, - { name: 'attr', re: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/ } - ], - - // for Prototype.LegacySelector.match and Element#match - assertions: { - tagName: function(element, matches) { - return matches[1].toUpperCase() == element.tagName.toUpperCase(); - }, - - className: function(element, matches) { - return Element.hasClassName(element, matches[1]); - }, - - id: function(element, matches) { - return element.id === matches[1]; - }, - - attrPresence: function(element, matches) { - return Element.hasAttribute(element, matches[1]); - }, - - attr: function(element, matches) { - var nodeValue = Element.readAttribute(element, matches[1]); - return nodeValue && Prototype.LegacySelector.operators[matches[2]](nodeValue, matches[5] || matches[6]); - } - }, - - handlers: { - // UTILITY FUNCTIONS - // joins two collections - concat: function(a, b) { - for (var i = 0, node; node = b[i]; i++) - a.push(node); - return a; - }, - - // marks an array of nodes for counting - mark: function(nodes) { - var _true = Prototype.emptyFunction; - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = _true; - return nodes; - }, - - unmark: (function(){ - - // IE improperly serializes _countedByPrototype in (inner|outer)HTML - // due to node properties being mapped directly to attributes - var PROPERTIES_ATTRIBUTES_MAP = (function(){ - var el = document.createElement('div'), - isBuggy = false, - propName = '_countedByPrototype', - value = 'x'; - el[propName] = value; - isBuggy = (el.getAttribute(propName) === value); - el = null; - return isBuggy; - })(); - - return PROPERTIES_ATTRIBUTES_MAP ? - function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node.removeAttribute('_countedByPrototype'); - return nodes; - } : - function(nodes) { - for (var i = 0, node; node = nodes[i]; i++) - node._countedByPrototype = void 0; - return nodes; - } - })(), - - // mark each child node with its position (for nth calls) - // "ofType" flag indicates whether we're indexing for nth-of-type - // rather than nth-child - index: function(parentNode, reverse, ofType) { - parentNode._countedByPrototype = Prototype.emptyFunction; - if (reverse) { - for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) { - var node = nodes[i]; - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; - } - } else { - for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++) - if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++; - } - }, - - // filters out duplicates and extends all nodes - unique: function(nodes) { - if (nodes.length == 0) return nodes; - var results = [], n; - for (var i = 0, l = nodes.length; i < l; i++) - // use `typeof` operator to prevent errors - if (typeof (n = nodes[i])._countedByPrototype == 'undefined') { - n._countedByPrototype = Prototype.emptyFunction; - results.push(n); - } - return Prototype.LegacySelector.handlers.unmark(results); - }, - - // COMBINATOR FUNCTIONS - descendant: function(nodes) { - var h = Prototype.LegacySelector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName('*')); - return results; - }, - - child: function(nodes) { - var h = Prototype.LegacySelector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) { - for (var j = 0, child; child = node.childNodes[j]; j++) - if (child.nodeType == 1 && child.tagName != '!') results.push(child); - } - return results; - }, - - adjacent: function(nodes) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - var next = this.nextElementSibling(node); - if (next) results.push(next); - } - return results; - }, - - laterSibling: function(nodes) { - var h = Prototype.LegacySelector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - h.concat(results, Element.nextSiblings(node)); - return results; - }, - - nextElementSibling: function(node) { - while (node = node.nextSibling) - if (node.nodeType == 1) return node; - return null; - }, - - previousElementSibling: function(node) { - while (node = node.previousSibling) - if (node.nodeType == 1) return node; - return null; - }, - - // TOKEN FUNCTIONS - tagName: function(nodes, root, tagName, combinator) { - var uTagName = tagName.toUpperCase(); - var results = [], h = Prototype.LegacySelector.handlers; - if (nodes) { - if (combinator) { - // fastlane for ordinary descendant combinators - if (combinator == "descendant") { - for (var i = 0, node; node = nodes[i]; i++) - h.concat(results, node.getElementsByTagName(tagName)); - return results; - } else nodes = this[combinator](nodes); - if (tagName == "*") return nodes; - } - for (var i = 0, node; node = nodes[i]; i++) - if (node.tagName.toUpperCase() === uTagName) results.push(node); - return results; - } else return root.getElementsByTagName(tagName); - }, - - id: function(nodes, root, id, combinator) { - var targetNode = $(id), h = Prototype.LegacySelector.handlers; - - if (root == document) { - // We don't have to deal with orphan nodes. Easy. - if (!targetNode) return []; - if (!nodes) return [targetNode]; - } else { - // In IE, we can check sourceIndex to see if root is attached - // to the document. If not (or if sourceIndex is not present), - // we do it the hard way. - if (!root.sourceIndex || root.sourceIndex < 1) { - var nodes = root.getElementsByTagName('*'); - for (var j = 0, node; node = nodes[j]; j++) { - if (node.id === id) return [node]; - } - } - } - - if (nodes) { - if (combinator) { - if (combinator == 'child') { - for (var i = 0, node; node = nodes[i]; i++) - if (targetNode.parentNode == node) return [targetNode]; - } else if (combinator == 'descendant') { - for (var i = 0, node; node = nodes[i]; i++) - if (Element.descendantOf(targetNode, node)) return [targetNode]; - } else if (combinator == 'adjacent') { - for (var i = 0, node; node = nodes[i]; i++) - if (Prototype.LegacySelector.handlers.previousElementSibling(targetNode) == node) - return [targetNode]; - } else nodes = h[combinator](nodes); - } - for (var i = 0, node; node = nodes[i]; i++) - if (node == targetNode) return [targetNode]; - return []; - } - return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : []; - }, - - className: function(nodes, root, className, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - return Prototype.LegacySelector.handlers.byClassName(nodes, root, className); - }, - - byClassName: function(nodes, root, className) { - if (!nodes) nodes = Prototype.LegacySelector.handlers.descendant([root]); - var needle = ' ' + className + ' '; - for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) { - nodeClassName = node.className; - if (nodeClassName.length == 0) continue; - if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle)) - results.push(node); - } - return results; - }, - - attrPresence: function(nodes, root, attr, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - var results = []; - for (var i = 0, node; node = nodes[i]; i++) - if (Element.hasAttribute(node, attr)) results.push(node); - return results; - }, - - attr: function(nodes, root, attr, value, operator, combinator) { - if (!nodes) nodes = root.getElementsByTagName("*"); - if (nodes && combinator) nodes = this[combinator](nodes); - var handler = Prototype.LegacySelector.operators[operator], results = []; - for (var i = 0, node; node = nodes[i]; i++) { - var nodeValue = Element.readAttribute(node, attr); - if (nodeValue === null) continue; - if (handler(nodeValue, value)) results.push(node); - } - return results; - }, - - pseudo: function(nodes, name, value, root, combinator) { - if (nodes && combinator) nodes = this[combinator](nodes); - if (!nodes) nodes = root.getElementsByTagName("*"); - return Prototype.LegacySelector.pseudos[name](nodes, value, root); - } - }, - - pseudos: { - 'first-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Prototype.LegacySelector.handlers.previousElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'last-child': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - if (Prototype.LegacySelector.handlers.nextElementSibling(node)) continue; - results.push(node); - } - return results; - }, - 'only-child': function(nodes, value, root) { - var h = Prototype.LegacySelector.handlers; - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!h.previousElementSibling(node) && !h.nextElementSibling(node)) - results.push(node); - return results; - }, - 'nth-child': function(nodes, formula, root) { - return Prototype.LegacySelector.pseudos.nth(nodes, formula, root); - }, - 'nth-last-child': function(nodes, formula, root) { - return Prototype.LegacySelector.pseudos.nth(nodes, formula, root, true); - }, - 'nth-of-type': function(nodes, formula, root) { - return Prototype.LegacySelector.pseudos.nth(nodes, formula, root, false, true); - }, - 'nth-last-of-type': function(nodes, formula, root) { - return Prototype.LegacySelector.pseudos.nth(nodes, formula, root, true, true); - }, - 'first-of-type': function(nodes, formula, root) { - return Prototype.LegacySelector.pseudos.nth(nodes, "1", root, false, true); - }, - 'last-of-type': function(nodes, formula, root) { - return Prototype.LegacySelector.pseudos.nth(nodes, "1", root, true, true); - }, - 'only-of-type': function(nodes, formula, root) { - var p = Prototype.LegacySelector.pseudos; - return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root); - }, - - // handles the an+b logic - getIndices: function(a, b, total) { - if (a == 0) return b > 0 ? [b] : []; - return $R(1, total).inject([], function(memo, i) { - if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i); - return memo; - }); - }, - - // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type - nth: function(nodes, formula, root, reverse, ofType) { - if (nodes.length == 0) return []; - if (formula == 'even') formula = '2n+0'; - if (formula == 'odd') formula = '2n+1'; - var h = Prototype.LegacySelector.handlers, results = [], indexed = [], m; - h.mark(nodes); - for (var i = 0, node; node = nodes[i]; i++) { - if (!node.parentNode._countedByPrototype) { - h.index(node.parentNode, reverse, ofType); - indexed.push(node.parentNode); - } - } - if (formula.match(/^\d+$/)) { // just a number - formula = Number(formula); - for (var i = 0, node; node = nodes[i]; i++) - if (node.nodeIndex == formula) results.push(node); - } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b - if (m[1] == "-") m[1] = -1; - var a = m[1] ? Number(m[1]) : 1; - var b = m[2] ? Number(m[2]) : 0; - var indices = Prototype.LegacySelector.pseudos.getIndices(a, b, nodes.length); - for (var i = 0, node, l = indices.length; node = nodes[i]; i++) { - for (var j = 0; j < l; j++) - if (node.nodeIndex == indices[j]) results.push(node); - } - } - h.unmark(nodes); - h.unmark(indexed); - return results; - }, - - 'empty': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) { - // IE treats comments as element nodes - if (node.tagName == '!' || node.firstChild) continue; - results.push(node); - } - return results; - }, - - 'not': function(nodes, selector, root) { - var h = Prototype.LegacySelector.handlers, selectorType, m; - var exclusions = new Prototype.LegacySelector(selector).findElements(root); - h.mark(exclusions); - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node._countedByPrototype) results.push(node); - h.unmark(exclusions); - return results; - }, - - 'enabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (!node.disabled && (!node.type || node.type !== 'hidden')) - results.push(node); - return results; - }, - - 'disabled': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.disabled) results.push(node); - return results; - }, - - 'checked': function(nodes, value, root) { - for (var i = 0, results = [], node; node = nodes[i]; i++) - if (node.checked) results.push(node); - return results; - } - }, - - operators: { - '=': function(nv, v) { return nv == v; }, - '!=': function(nv, v) { return nv != v; }, - '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); }, - '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); }, - '*=': function(nv, v) { return nv == v || nv && nv.include(v); }, - '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); }, - '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() + - '-').include('-' + (v || "").toUpperCase() + '-'); } - }, - - split: function(expression) { - var expressions = []; - expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) { - expressions.push(m[1].strip()); - }); - return expressions; - }, - - matchElements: function(elements, expression) { - var matches = $$(expression), h = Prototype.LegacySelector.handlers; - h.mark(matches); - for (var i = 0, results = [], element; element = elements[i]; i++) - if (element._countedByPrototype) results.push(element); - h.unmark(matches); - return results; - }, - - findElement: function(elements, expression, index) { - if (Object.isNumber(expression)) { - index = expression; expression = false; - } - return Prototype.LegacySelector.matchElements(elements, expression || '*')[index || 0]; - }, - - findChildElements: function(element, expressions) { - expressions = Prototype.LegacySelector.split(expressions.join(',')); - var results = [], h = Prototype.LegacySelector.handlers; - for (var i = 0, l = expressions.length, selector; i < l; i++) { - selector = new Prototype.LegacySelector(expressions[i].strip()); - h.concat(results, selector.findElements(element)); - } - return (l > 1) ? h.unique(results) : results; - } -}); diff --git a/vendor/legacy_selector/selector_engine.js b/vendor/legacy_selector/selector_engine.js deleted file mode 100644 index 3c5cf305f..000000000 --- a/vendor/legacy_selector/selector_engine.js +++ /dev/null @@ -1,15 +0,0 @@ -//= require "repository/legacy_selector" - -;(function(engine) { - function select(selector, scope) { - return engine.findChildElements(scope || document, [selector]); - } - - function match(element, selector) { - return !!engine.findElement([element], selector); - } - - Prototype.Selector.engine = engine; - Prototype.Selector.select = select; - Prototype.Selector.match = match; -})(Prototype.LegacySelector); diff --git a/vendor/nwmatcher/repository b/vendor/nwmatcher/repository deleted file mode 160000 index c9f5d5d4f..000000000 --- a/vendor/nwmatcher/repository +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c9f5d5d4fc4ca294477f803bb8d688a8d45de664 diff --git a/vendor/nwmatcher/selector_engine.js b/vendor/nwmatcher/selector_engine.js deleted file mode 100644 index 23af2afa8..000000000 --- a/vendor/nwmatcher/selector_engine.js +++ /dev/null @@ -1,16 +0,0 @@ -Prototype._original_property = window.NW; -//= require "repository/src/nwmatcher" - -;(function(engine) { - function select(selector, scope) { - return engine.select(selector, scope); - } - - Prototype.Selector.engine = engine; - Prototype.Selector.select = select; - Prototype.Selector.match = engine.match; -})(NW.Dom); - -// Restore globals. -window.NW = Prototype._original_property; -delete Prototype._original_property; diff --git a/vendor/pdoc b/vendor/pdoc deleted file mode 160000 index b8da8a0e3..000000000 --- a/vendor/pdoc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b8da8a0e3e33192bf74a0eecdcb88108bf9adcfd diff --git a/vendor/sizzle/repository b/vendor/sizzle/repository deleted file mode 160000 index a9eb3ca3c..000000000 --- a/vendor/sizzle/repository +++ /dev/null @@ -1 +0,0 @@ -Subproject commit a9eb3ca3c5e1b568057390f73da385809ac69340 diff --git a/vendor/sizzle/selector_engine.js b/vendor/sizzle/selector_engine.js deleted file mode 100644 index 40ecfbb16..000000000 --- a/vendor/sizzle/selector_engine.js +++ /dev/null @@ -1,59 +0,0 @@ -Prototype._original_property = window.Sizzle; - -;(function () { - function fakeDefine(fn) { - Prototype._actual_sizzle = fn(); - } - fakeDefine.amd = true; - - if (typeof define !== 'undefined' && define.amd) { - // RequireJS is loaded. We need to pretend to be `define` while Sizzle - // runs. - Prototype._original_define = define; - Prototype._actual_sizzle = null; - window.define = fakeDefine; - } -})(); - -//= require "repository/dist/sizzle" - -;(function() { - if (typeof Sizzle !== 'undefined') { - // Sizzle was properly defined. - return; - } - - if (typeof define !== 'undefined' && define.amd) { - // RequireJS. - // We should find Sizzle where we put it. And we need to restore the original `define`. - window.Sizzle = Prototype._actual_sizzle; - window.define = Prototype._original_define; - delete Prototype._actual_sizzle; - delete Prototype._original_define; - // TODO: Should we make our own `define` call here? - } else if (typeof module !== 'undefined' && module.exports) { - // Sizzle saw that it's in a CommonJS environment and attached itself to - // `module.exports` instead. - window.Sizzle = module.exports; - // Reset `module.exports`. - module.exports = {}; - } -})(); - -;(function(engine) { - function select(selector, scope) { - return engine(selector, scope || document); - } - - function match(element, selector) { - return engine.matches(selector, [element]).length == 1; - } - - Prototype.Selector.engine = engine; - Prototype.Selector.select = select; - Prototype.Selector.match = match; -})(window.Sizzle); - -// Restore globals. -window.Sizzle = Prototype._original_property; -delete Prototype._original_property; diff --git a/vendor/slick/repository b/vendor/slick/repository deleted file mode 160000 index b7d3a3305..000000000 --- a/vendor/slick/repository +++ /dev/null @@ -1 +0,0 @@ -Subproject commit b7d3a3305675cfaa326c55b3eb1d4c4d4f962744 diff --git a/vendor/slick/selector_engine.js b/vendor/slick/selector_engine.js deleted file mode 100644 index 11e5ca1b8..000000000 --- a/vendor/slick/selector_engine.js +++ /dev/null @@ -1,17 +0,0 @@ -Prototype._original_property = window.Slick; -//= require "repository/Source/Slick.Parser.js" -//= require "repository/Source/Slick.Finder.js" - -;(function(engine) { - function select(selector, scope) { - return engine.search(scope || document, selector); - } - - Prototype.Selector.engine = engine; - Prototype.Selector.select = select; - Prototype.Selector.match = engine.match; -})(Slick); - -// Restore globals. -window.Slick = Prototype._original_property; -delete Prototype._original_property; diff --git a/vendor/sprockets b/vendor/sprockets deleted file mode 160000 index 8860b7f54..000000000 --- a/vendor/sprockets +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8860b7f54d08dd4861bea1ca5de223555ad4b2c1