MochiKit-1.4.2/0000755000175000017500000000000011136470265012304 5ustar scottscottMochiKit-1.4.2/examples/0000755000175000017500000000000011136470265014122 5ustar scottscottMochiKit-1.4.2/examples/effects/0000755000175000017500000000000011136470264015540 5ustar scottscottMochiKit-1.4.2/examples/effects/effects_blind.html0000660000175000017500000000330311113647642021213 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us Effects functional test file

Effect.BlindUp/Effect.BlindDown

Lorem ipsum dolor sit amet test! test! test! test! test! test! test! test! test! test! Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet

BlindDown()

BlindUp()

MochiKit-1.4.2/examples/effects/effects_bigslide.html0000660000175000017500000000430211113647642021705 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us Effects functional test file

Effect.SlideDown/Effect.SlideUp

Start slide down | Start slide up | cancel() | inspect() | add content MochiKit-1.4.2/examples/effects/effects_grow_shrink.html0000660000175000017500000000216511113647642022464 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us Effects functional test file

Effect.Grow/Effect.Shrink

Lorem ipsum dolor sit amet

Grow: Grow()

Shrink: Shrink()

MochiKit-1.4.2/examples/effects/effects_combi.css0000660000175000017500000000046111102215702021024 0ustar scottscotth3 { clear: both; } .example { font-size: 1.0em; float: left; margin-right: 10px; margin-bottom: 10px; width: 112px; height: 112px; border: 4px solid #669; background-color: #ccf; text-align: center; padding: 1em 0.2em 0.2em 0.2em; } .demo { clear: both; } MochiKit-1.4.2/examples/effects/index.html0000660000175000017500000001415311113647642017540 0ustar scottscott Test Effects

Here are demos of all combination effects:

Click for Visual.appear demo
Click for Visual.fade demo
Click for Visual.puff demo
Click for Visual.blindDown demo
Click for Visual.blindUp demo
Click for Visual.switchOff demo
Click for Visual.slideDown demo
Click for Visual.slideUp demo
Click for Visual.dropOut demo
Click for Visual.shake demo
Click for Visual.pulsate demo
Click for Visual.squish demo
Click for Visual.fold demo
Click for Visual.grow demo
Click for Visual.shrink demo
Click for Visual.Highlight demo

Here are all demos on one single element:

Click to see the selected effect
  in slow-motion

Links to other samples:

MochiKit-1.4.2/examples/effects/effects_blindslide.html0000660000175000017500000000406011113647642022235 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us Effects functional test file

Highlight | BlindUp | BlindDown | SlideUp | SlideDown
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Maecenas enim. Nulla facilisi. Vestibulum accumsan augue vulputate justo. Fusce faucibus. Sed blandit, neque sed lacinia nonummy, diam quam imperdiet justo, at dictum augue nunc a neque. Sed urna lacus, tincidunt at, aliquam id, fringilla id, felis. Vivamus feugiat molestie quam. Sed id dolor. Sed ac purus id sapien sollicitudin ultricies. Aliquam hendrerit orci et odio. Suspendisse volutpat wisi at sem. Integer eget nulla. Duis eu diam a nunc condimentum tempus. Praesent gravida metus vitae massa. Aliquam neque magna, fringilla eu, porta id, interdum sit amet, dui. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin lorem est, ultrices sit amet, condimentum vitae, vehicula a, massa.
MochiKit-1.4.2/examples/effects/effects_scroll.html0000660000175000017500000001631711113647642021432 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us ScrollTo effect functional test

scroll (slow-mo) down-below..., scroll last-heading

first-headingHeading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

DOWN BELOWHeading 2

scroll...

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

Heading 2

MochiKit-1.4.2/examples/effects/full.html0000660000175000017500000000577211113647642017402 0ustar scottscott Full Effects Test Suite

Full Effects Test Suite

  • fade
  • appear
  • puff
  • blindDown
  • blindUp
  • switchOff
  • slideDown
  • slideUp
  • dropOut
  • shake
  • pulsate
  • squish
  • fold
  • grow
  • shrink
  • Highlight
  • Morph font
  • Morph color
  • toggle (blind)
  • toggle (slide)
  • toggle (appear)
  • toggle (size)
Click on one of the left to see the effect
MochiKit-1.4.2/examples/effects/effects_queue.html0000660000175000017500000000447111113647642021256 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us Effects functional test file

Effect.Queue

Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet

Lorem ipsum dolor sit amet

Start queued effects (in 'global' queue)
Do a bit sliding in parallel, with a scoped queue
MochiKit-1.4.2/examples/effects/effects_queue_limit.html0000660000175000017500000000277211113647642022456 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us Effects functional test file

Effect.Queue limit

up down
Do a bit sliding in parallel, with a scoped queue, but I am limited to one : ) so don't try over and over again...
MochiKit-1.4.2/examples/effects/effects_fadeappear.html0000660000175000017500000000563011113647642022220 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us fade/appear effect functional test

Note: these tests use the browser default CSS style rules.

DIV

TEST
MochiKit.Visual.fade | MochiKit.Visual.appear

SPAN

TEST
MochiKit.Visual.fade | MochiKit.Visual.appear

P

TEST


MochiKit.Visual.fade | MochiKit.Visual.appear

IMG

test image
MochiKit.Visual.fade | MochiKit.Visual.appear

The following elements are not supported with fade/appear on all browsers!

TABLE

TEST
MochiKit.Visual.fade | MochiKit.Visual.appear

TBODY

TEST
MochiKit.Visual.fade | MochiKit.Visual.appear

TR

TEST
MochiKit.Visual.fade | MochiKit.Visual.appear

TD

TEST
MochiKit.Visual.fade | MochiKit.Visual.appear MochiKit-1.4.2/examples/effects/effects_onload.html0000660000175000017500000000444511113647642021407 0ustar scottscott script.aculo.us Effects functional test file

script.aculo.us Effects functional test file

Effect.Highlight

slide down
(highlight to red)
(highlight to greenish)
(bottom-right-grow)
click to test shake
click to test puff
show puff div again test appear test grow test pulsate
pulsate
MochiKit-1.4.2/examples/effects/icon.png0000660000175000017500000000043111102215702017155 0ustar scottscottPNG  IHDR exgAMAOX2tEXtSoftwareAdobe ImageReadyqe<9PLTEBBΔ΄!!!!ssRRֵcc絵{쭃cfIDATxl @CۏZ!@XUgBއ>K 0'-Igt&p! f&ϴyL.h/EĨ0 ݫIENDB`MochiKit-1.4.2/examples/effects/effects_slide.html0000660000175000017500000000361611113647642021232 0ustar scottscott Slide effects test MochiKit-1.4.2/examples/key_events/0000755000175000017500000000000011136470264016275 5ustar scottscottMochiKit-1.4.2/examples/key_events/key_events.js0000660000175000017500000000475611102215704021006 0ustar scottscott/* Key Events: A Really Simple Key Handler */ KeyEvents = { handled: false, handleF1: function() { replaceChildNodes('specialMessage', 'You invoked the special F1 handler!'); }, handleEscape: function() { replaceChildNodes('specialMessage', 'You invoked the special Escape handler!'); }, updateModifiers: function(e) { var modifiers = e.modifier(); replaceChildNodes('shift', modifiers.shift); replaceChildNodes('ctrl', modifiers.ctrl); replaceChildNodes('alt', modifiers.alt); replaceChildNodes('meta', modifiers.meta); } }; KeyEvents.specialKeyMap = { 'KEY_F1': KeyEvents.handleF1, 'KEY_ESCAPE': KeyEvents.handleEscape }; connect(document, 'onkeydown', function(e) { if (getElement('stopBox').checked == true) { e.preventDefault(); } // We're storing a handled flag to work around a Safari bug: // http://bugs.webkit.org/show_bug.cgi?id=3387 if (!KeyEvents.handled) { var key = e.key(); var fn = KeyEvents.specialKeyMap[key.string]; if (fn) { fn(); } replaceChildNodes('onkeydown_code', key.code); replaceChildNodes('onkeydown_string', key.string); KeyEvents.updateModifiers(e); } KeyEvents.handled = true; }); connect(document, 'onkeyup', function(e) { if (getElement('stopBox').checked == true) { e.preventDefault(); } KeyEvents.handled = false; var key = e.key(); replaceChildNodes('onkeyup_code', key.code); replaceChildNodes('onkeyup_string', key.string); KeyEvents.updateModifiers(e); }); connect(document, 'onkeypress', function(e) { if (getElement('stopBox').checked == true) { e.preventDefault(); } var key = e.key(); replaceChildNodes('onkeypress_code', key.code); replaceChildNodes('onkeypress_string', key.string); KeyEvents.updateModifiers(e); }); connect(window, 'onload', function() { var elems = getElementsByTagAndClassName("A", "view-source"); var page = "key_events/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } });MochiKit-1.4.2/examples/key_events/index.html0000660000175000017500000000437611113647642020303 0ustar scottscott Signal Example

Key Events with MochiKit

This is an example of one might implement a key listener with MochiKit’s Signal.

For a detailed description of what happens under the hood, check out key_events.js.

View Source: [ index.html | key_events.js | key_events.css ]

Check this box to test preventDefault() in your browser:

This text is replaced with a message when you press Escape or F1.

Event Key Code Key String
onkeydown - -
onkeyup - -
onkeypress - -

Modifiers

Shift Ctrl Alt (Option) Meta (Command)
- - - -
MochiKit-1.4.2/examples/key_events/key_events.css0000660000175000017500000000010611102215704021143 0ustar scottscotth1 { font-size: 2em; color: #4B4545; text-align: center; }MochiKit-1.4.2/examples/color_wheel/0000755000175000017500000000000011136470264016423 5ustar scottscottMochiKit-1.4.2/examples/color_wheel/index.html0000660000175000017500000000240611113647642020421 0ustar scottscott Demo of MochiKit.Color

Color Wheel

Animated visualization of all the CSS3 colors by: hue (angle), saturation (distance), luminance (time/alpha).
Uses MochiKit's MochiKit.Color, MochiKit.DOM, and MochiKit.Async.
View Source: [ index.html | color_wheel.js ]
MochiKit-1.4.2/examples/color_wheel/color_wheel.js0000660000175000017500000000546711102215702021260 0ustar scottscottvar radius = 225; var twoPI = Math.PI * 2; var amplification = 10; var calcAlpha = function (target, lightness) { return Math.max(1.0 - (Math.abs(lightness - target) * amplification), 0); }; var makeColorDiv = function (name) { var c = Color.fromName(name); var hsl = c.asHSL(); var r = hsl.s * radius; var e = DIV({"style": { "color": Color.fromHSL(hsl).toString(), "width": "100px", "height": "30px", "position": "absolute", "verticalAlign": "middle", "textAlign": "center", "left": Math.floor((Math.cos(hsl.h * twoPI) * r) - 50) + "px", "top": Math.floor((Math.sin(hsl.h * twoPI) * r)) + "px" }}, name ); // hsl.a = 0; return [c, e]; }; var colorWheelOnLoad = function () { var seenColors = {}; var colors = Color.namedColors(); var colorDivs = []; for (var k in colors) { var val = colors[k]; if (val in seenColors) { continue; } colorDivs.push(makeColorDiv(k)); } swapDOM( "color_wheel", DIV(null, map(itemgetter(1), colorDivs)) ); var colorCanary = DIV({"style":{"color": "blue"}}, ""); try { colorCanary.style.color = "rgba(100,100,100,0.5)"; } catch (e) { // IE passtastic } var colorFunc; // Check for CSS3 HSL support if (colorCanary.style.color == "blue") { var bgColor = Color.fromBackground(); colorFunc = function (color, alpha) { return bgColor.blendedColor(color, alpha).toHexString(); }; } else { colorFunc = function (color, alpha) { return color.colorWithAlpha(alpha).toRGBString(); } } // Per-frame animation var intervalFunc = function (cycle, timeout) { var target = 0.5 + (0.5 * Math.sin(Math.PI * (cycle / 180))); for (var i = 0; i < colorDivs.length; i++) { var cd = colorDivs[i]; var color = cd[0]; var alpha = calcAlpha(target, color.asHSL().l); var style = cd[1].style; if (alpha == 0) { style.display = "none"; } else { style.display =""; style.color = colorFunc(color, alpha); } } callLater(timeout, arguments.callee, cycle + 2, timeout); }; // < 5 fps intervalFunc(0, 1/5); }; addLoadEvent(colorWheelOnLoad); // rewrite the view-source links addLoadEvent(function () { var elems = getElementsByTagAndClassName("A", "view-source"); var page = "color_wheel/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } }); MochiKit-1.4.2/examples/color_wheel/color_wheel.css0000660000175000017500000000023311102215702021416 0ustar scottscotth1 { text-align: center; } #docs { text-align: center; } #source { text-align: center; } #color_wheel_container { position:absolute; left: 50%; top: 50% } MochiKit-1.4.2/examples/simple_dnd/0000755000175000017500000000000011136470265016240 5ustar scottscottMochiKit-1.4.2/examples/simple_dnd/dnd_scroll.html0000660000175000017500000000441011113647642021246 0ustar scottscott script.aculo.us Drag and drop functional test file

script.aculo.us Drag and drop functional test file

Draggables/Droppables

  • Relatively here!
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one
  • one





MochiKit-1.4.2/examples/simple_dnd/dnd_hoverclass.html0000660000175000017500000000307611113647642022130 0ustar  scottscott

script.aculo.us Drag and drop functional test file
    
    
    
    




script.aculo.us Drag and drop functional test file

w/o hoverclass

### DROP HERE ###

Product2 <-- drag this!

w/ hoverclass

### DROP HERE ###
MochiKit-1.4.2/examples/simple_dnd/index.html0000660000175000017500000001106411113647642020235 0ustar scottscott Test Drag and drop with MochiKit

Drag and Drop examples.

test drag 1
test drag 2 (horizontal)
test drag 3 (vertical)
test drag 4 (selectclass)
test drag 5 (fixed)
test drag 6 (absolute)
test drag 7 (relative)
test drag 8 (handle)
handle for drag 8
test drop 1
test drop 2 (hoverclass)
test drop 3 (activeclass)
test drop 4 (hoverFunc)
test drop 5 (activeFunc)
test drop 6
No select
Links to other samples:
MochiKit-1.4.2/examples/simple_dnd/dnd_boxes.html0000660000175000017500000000420611113647642021073 0ustar scottscott script.aculo.us Drag and drop functional test file

script.aculo.us Drag and drop functional test file

Draggables/Droppables

drag here
Revert?
drag here
Revert?
accepts first box
accepts second box
MochiKit-1.4.2/examples/simple_dnd/simple_dnd.css0000660000175000017500000000157011102215706021057 0ustar scottscott.drag { background-color: blue; width: 100px; padding: 5px; margin: 10px; border: 1px solid black; } #dropzones { margin-top: 100px; display: inline; } .drop { background-color: red; width: 100px; padding: 5px; margin: 10px; border: 1px solid black; display: inline; } .droptrans { width: 100px; padding: 5px; margin: 10px; border: 1px solid black; } .drop-hover { border: 2px solid green; } .drop-active { background-color: #FF79ED; } .drag-select { background-color: green; } #drag-5 { position: fixed; top: 100px; left: 200px; } #drag-6 { position: absolute; top: 100px; left: 350px; } #drag-7 { position: relative; top: -100px; left: 500px; } #drop-6 { display: inline; } #droptext { margin-top: 20px; border: 1px dashed black; padding: 10px; } MochiKit-1.4.2/examples/simple_dnd/dnd_ghost.html0000660000175000017500000000326711113647642021105 0ustar scottscott script.aculo.us Drag and drop functional test file
(inside position:relative container)

script.aculo.us Drag and drop functional test file

Draggables/Droppables

Ghosting effect
test!

alert contents of test div
Ghost effect
MochiKit-1.4.2/examples/simple_dnd/dnd_full.html0000660000175000017500000000712011113647642020713 0ustar scottscott script.aculo.us Drag and drop functional test file

script.aculo.us Drag and drop functional test file

Draggables/Droppables

drag here
Revert?
drag here
Revert?
testtest
MochiKit-1.4.2/examples/simple_dnd/dnd_snap.html0000660000175000017500000000330111113647642020707 0ustar scottscott script.aculo.us Drag and drop functional test file

script.aculo.us Drag and drop functional test file

Draggables/Droppables

Normal box
snap: 25
snap: [5,25]
snap: procedural (e.g. constrain to box)
MochiKit-1.4.2/examples/logging_pane/0000755000175000017500000000000011136470264016552 5ustar scottscottMochiKit-1.4.2/examples/logging_pane/index.html0000660000175000017500000000412011113647642020543 0ustar scottscott Demo of MochiKit.LoggingPane

MochiKit.LoggingPane

Demonstrates MochiKit's MochiKit.Logging and MochiKit.LoggingPane.

Click one of the Logging Panes to pop up a view, and then start clicking on Logging Actions to see it in action!

Logging Panes:
Logging Actions:
View Source:
MochiKit-1.4.2/examples/logging_pane/logging_pane.js0000660000175000017500000000061011102215704021521 0ustar scottscott// rewrite the view-source links addLoadEvent(function () { var elems = getElementsByTagAndClassName("A", "view-source"); var page = "logging_pane/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } }); MochiKit-1.4.2/examples/logging_pane/logging_pane.css0000660000175000017500000000334511102215704021705 0ustar scottscotth1 { font-size: 2em; color: #4B4545; text-align: center; } table.datagrid { width: 100%; border-collapse: collapse; } table.datagrid thead th { text-align: left; background-color: #4B4545; background-repeat: no-repeat; background-position: right center; color: white; font-weight: bold; padding: .3em .7em; font-size: .9em; padding-right: 5px; background-repeat: no-repeat; background-position: 95% right; } table.datagrid thead th a { color: white; text-decoration: none; font-size: 1.0em; background-repeat: no-repeat; background-position: center right; padding-right: 15px; } table.datagrid thead th.over { background-color: #746B6B; cursor: pointer; } table.datagrid tbody th { font-weight: bold; } table.datagrid tbody td, table.datagrid tbody th { text-align: left; padding: .3em .7em; border-bottom: 1px solid #eee; } table.datagrid tbody tr.alternate td, table.datagrid tbody tr.alternate th { background-color: #f1f1f1; } table.datagrid tfoot td, table.datagrid tfoot th { background-color: #FFFEE3; color: #4B4545; padding: .5em; font-weight: bold; border-top: 2px solid #4B4545; } table.datagrid tfoot th { text-align: left; } table.datagrid tfoot td { } .invisible { display: none; } input.textbox, textarea { border: 1px solid #CCCCCC; font-size: .95em; padding: 2px 4px; margin-top: .3em; } input.textbox:focus, textarea:focus { background-color: #FFFEE3; } .highlight { font-weight: bold; }; form { margin: 0; padding: 0; } fieldset { border: none; margin: 0; padding: 0; } fieldset label { font-weight: bold; color: #4B4545; } fieldset .field { margin-bottom: 1em; } label.error { color: red; } MochiKit-1.4.2/examples/ajax_tables/0000755000175000017500000000000011136470264016376 5ustar scottscottMochiKit-1.4.2/examples/ajax_tables/ajax_tables.js0000660000175000017500000003144111102215706021201 0ustar scottscott/* On page load, the SortableManager: - Rips out all of the elements with the mochi-example class. - Finds the elements with the mochi-template class and saves them for later parsing with "MochiTAL". - Finds the anchor tags with the mochi:dataformat attribute and gives them onclick behvaiors to load new data, using their href as the data source. This makes your XML or JSON look like a normal link to a search engine (or javascript-disabled browser). - Clones the thead element from the table because it will be replaced on each sort. - Sets up a default sort key of "domain_name" and queues a load of the json document. On data load, the SortableManager: - Parses the table data from the document (columns list, rows list-of-lists) and turns them into a list of [{column:value, ...}] objects for easy sorting and column order stability. - Chooses the default (or previous) sort state and triggers a sort request On sort request: - Replaces the cloned thead element with a copy of it that has the sort indicator (↑ or ↓) for the most recently sorted column (matched up to the first field in the th's mochi:sortcolumn attribute), and attaches onclick, onmousedown, onmouseover, onmouseout behaviors to them. The second field of mochi:sortcolumn attribute is used to perform a non-string sort. - Performs the sort on the domains list. If the second field of mochi:sortcolumn was not "str", then a custom function is used and the results are stored away in a __sort__ key, which is then used to perform the sort (read: shwartzian transform). - Calls processMochiTAL on the page, which finds the mochi-template sections and then looks for mochi:repeat and mochi:content attributes on them, using the data object. */ processMochiTAL = function (dom, data) { /*** A TAL-esque template attribute language processor, including content replacement and repeat ***/ // nodeType == 1 is an element, we're leaving // text nodes alone. if (dom.nodeType != 1) { return; } var attr; // duplicate this element for each item in the // given list, and then process the duplicated // element again (sans mochi:repeat tag) attr = getAttribute(dom, "mochi:repeat"); if (attr) { dom.removeAttribute("mochi:repeat"); var parent = dom.parentNode; attr = attr.split(" "); var name = attr[0]; var lst = valueForKeyPath(data, attr[1]); if (!lst) { return; } for (var i = 0; i < lst.length; i++) { data[name] = lst[i]; var newDOM = dom.cloneNode(true); processMochiTAL(newDOM, data); parent.insertBefore(newDOM, dom); } parent.removeChild(dom); return; } // do content replacement if there's a mochi:content attribute // on the element attr = getAttribute(dom, "mochi:content"); if (attr) { dom.removeAttribute("mochi:content"); replaceChildNodes(dom, valueForKeyPath(data, attr)); return; } // we make a shallow copy of the current list of child nodes // because it *will* change if there's a mochi:repeat in there! var nodes = list(dom.childNodes); for (var i = 0; i < nodes.length; i++) { processMochiTAL(nodes[i], data); } }; mouseOverFunc = function () { addElementClass(this, "over"); }; mouseOutFunc = function () { removeElementClass(this, "over"); }; ignoreEvent = function (ev) { if (ev && ev.preventDefault) { ev.preventDefault(); ev.stopPropagation(); } else if (typeof(event) != 'undefined') { event.cancelBubble = false; event.returnValue = false; } }; SortTransforms = { "str": operator.identity, "istr": function (s) { return s.toLowerCase(); }, "isoDate": isoDate }; getAttribute = function (dom, key) { try { return dom.getAttribute(key); } catch (e) { return null; } }; datatableFromXMLRequest = function (req) { /*** This effectively converts domains.xml to the same form as domains.json ***/ var xml = req.responseXML; var nodes = xml.getElementsByTagName("column"); var rval = {"columns": map(scrapeText, nodes)}; var rows = []; nodes = xml.getElementsByTagName("row") for (var i = 0; i < nodes.length; i++) { var cells = nodes[i].getElementsByTagName("cell"); rows.push(map(scrapeText, cells)); } rval.rows = rows; return rval; }; loadFromDataAnchor = function (ev) { ignoreEvent(ev); var format = this.getAttribute("mochi:dataformat"); var href = this.href; sortableManager.loadFromURL(format, href); }; valueForKeyPath = function (data, keyPath) { var chunks = keyPath.split("."); while (chunks.length && data) { data = data[chunks.shift()]; } return data; }; SortableManager = function () { this.thead = null; this.thead_proto = null; this.tbody = null; this.deferred = null; this.columns = []; this.rows = []; this.templates = []; this.sortState = {}; bindMethods(this); }; SortableManager.prototype = { "initialize": function () { // just rip all mochi-examples out of the DOM var examples = getElementsByTagAndClassName(null, "mochi-example"); while (examples.length) { swapDOM(examples.pop(), null); } // make a template list var templates = getElementsByTagAndClassName(null, "mochi-template"); for (var i = 0; i < templates.length; i++) { var template = templates[i]; var proto = template.cloneNode(true); removeElementClass(proto, "mochi-template"); this.templates.push({ "template": proto, "node": template }); } // set up the data anchors to do loads var anchors = getElementsByTagAndClassName("a", null); for (var i = 0; i < anchors.length; i++) { var node = anchors[i]; var format = getAttribute(node, "mochi:dataformat"); if (format) { node.onclick = loadFromDataAnchor; } } // to find sort columns this.thead = getElementsByTagAndClassName("thead", null)[0]; this.thead_proto = this.thead.cloneNode(true); this.sortkey = "domain_name"; this.loadFromURL("json", "domains.json"); }, "loadFromURL": function (format, url) { log('loadFromURL', format, url); var d; if (this.deferred) { this.deferred.cancel(); } if (format == "xml") { var d = doXHR(url, { mimeType: 'text/xml', headers: {Accept: 'text/xml'} }); d.addCallback(datatableFromXMLRequest); } else if (format == "json") { d = loadJSONDoc(url); } else { throw new TypeError("format " + repr(format) + " not supported"); } // keep track of the current deferred, so that we can cancel it this.deferred = d; var self = this; // on success or error, remove the current deferred because it has // completed, and pass through the result or error d.addBoth(function (res) { self.deferred = null; log('loadFromURL success'); return res; }); // on success, tag the result with the format used so we can display // it d.addCallback(function (res) { res.format = format; return res; }); // call this.initWithData(data) once it's ready d.addCallback(this.initWithData); // if anything goes wrong, except for a simple cancellation, // then log the error and show the logger d.addErrback(function (err) { if (err instanceof CancelledError) { return; } logError(err); logger.debuggingBookmarklet(); }); return d; }, "initWithData": function (data) { /*** Initialize the SortableManager with a table object ***/ // reformat to [{column:value, ...}, ...] style as the domains key var domains = []; var rows = data.rows; var cols = data.columns; for (var i = 0; i < rows.length; i++) { var row = rows[i]; var domain = {}; for (var j = 0; j < cols.length; j++) { domain[cols[j]] = row[j]; } domains.push(domain); } data.domains = domains; this.data = data; // perform a sort and display based upon the previous sort state, // defaulting to an ascending sort if this is the first sort var order = this.sortState[this.sortkey]; if (typeof(order) == 'undefined') { order = true; } this.drawSortedRows(this.sortkey, order, false); }, "onSortClick": function (name) { /*** Return a sort function for click events ***/ // save ourselves from doing a bind var self = this; // on click, flip the last sort order of that column and sort return function () { log('onSortClick', name); var order = self.sortState[name]; if (typeof(order) == 'undefined') { // if it's never been sorted by this column, sort ascending order = true; } else if (self.sortkey == name) { // if this column was sorted most recently, flip the sort order order = !((typeof(order) == 'undefined') ? false : order); } self.drawSortedRows(name, order, true); }; }, "drawSortedRows": function (key, forward, clicked) { /*** Draw the new sorted table body, and modify the column headers if appropriate ***/ log('drawSortedRows', key, forward); // save it so we can flip next time this.sortState[key] = forward; this.sortkey = key; var sortstyle; // setup the sort columns var thead = this.thead_proto.cloneNode(true); var cols = thead.getElementsByTagName("th"); for (var i = 0; i < cols.length; i++) { var col = cols[i]; var sortinfo = getAttribute(col, "mochi:sortcolumn").split(" "); var sortkey = sortinfo[0]; col.onclick = this.onSortClick(sortkey); col.onmousedown = ignoreEvent; col.onmouseover = mouseOverFunc; col.onmouseout = mouseOutFunc; // if this is the sorted column if (sortkey == key) { sortstyle = sortinfo[1]; // \u2193 is down arrow, \u2191 is up arrow // forward sorts mean the rows get bigger going down var arrow = (forward ? "\u2193" : "\u2191"); // add the character to the column header col.appendChild(SPAN(null, arrow)); if (clicked) { col.onmouseover(); } } } this.thead = swapDOM(this.thead, thead); // apply a sort transform to a temporary column named __sort__, // and do the sort based on that column if (!sortstyle) { sortstyle = "str"; } var sortfunc = SortTransforms[sortstyle]; if (!sortfunc) { throw new TypeError("unsupported sort style " + repr(sortstyle)); } var domains = this.data.domains; for (var i = 0; i < domains.length; i++) { var domain = domains[i]; domain.__sort__ = sortfunc(domain[key]); } // perform the sort based on the state given (forward or reverse) var cmp = (forward ? keyComparator : reverseKeyComparator); domains.sort(cmp("__sort__")); // process every template with the given data // and put the processed templates in the DOM for (var i = 0; i < this.templates.length; i++) { log('template', i, template); var template = this.templates[i]; var dom = template.template.cloneNode(true); processMochiTAL(dom, this.data); template.node = swapDOM(template.node, dom); } } }; // create the global SortableManager and initialize it on page load sortableManager = new SortableManager(); addLoadEvent(sortableManager.initialize); // rewrite the view-source links addLoadEvent(function () { var elems = getElementsByTagAndClassName("A", "view-source"); var page = "ajax_tables/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } }); MochiKit-1.4.2/examples/ajax_tables/domains.xml0000660000175000017500000000214511102215706020541 0ustar scottscott domain_name create_date expiry_date organization_name xml.com 1996-09-30 2012-09-29 Tim Bray mochibot.com 2005-02-10 2007-02-10 Jameson Hsu pythonmac.org 2003-09-24 2006-09-24 Bob Ippolito undefined.org 2000-01-10 2006-01-10 Robert J Ippolito python.org 1995-03-27 2007-03-28 Python Software Foundation MochiKit-1.4.2/examples/ajax_tables/index.html0000660000175000017500000001013211113647642020367 0ustar scottscott Sortable Tables from Scratch with MochiKit

Sortable Ajax Tables in JSON and XML with MochiKit

This is an example of how one might use MochiKit to do sortable tables from data given by the server in either JSON or XML format. It uses MochiKit.Async to fetch the data, and MochiKit.DOM to display it.

Includes a micro implementation of something TAL-esque (called "MochiTAL" in the source, using a mochi: namespace). For a more detailed description of what happens under the covers, view the ajax_tables.js source and look at the comments.

View Source: [ index.html | ajax_tables.js | domains.json | domains.xml ]
Load data: [ domains.json | domains.xml ] (current format: loading)
Domain Name Creation Date Expiry Date Organization Name
mochibot.com 2005-02-10 2007-02-10 Jameson Hsu
pythonmac.org 2003-09-24 2006-09-24 Bob Ippolito
undefined.org 2000-01-10 2006-01-10 Robert J Ippolito
python.org 1995-03-27 2007-03-28 Python Software Foundation
MochiKit-1.4.2/examples/ajax_tables/domains.json0000660000175000017500000000073411102215706020714 0ustar scottscott{ "columns": [ "domain_name", "create_date", "expiry_date", "organization_name"], "rows": [ ["json.org", "2000-05-08", "2006-05-08", "Douglas Crockford"], ["mochibot.com", "2005-02-10", "2007-02-10", "Jameson Hsu"], ["pythonmac.org", "2003-09-24", "2006-09-24", "Bob Ippolito"], ["undefined.org", "2000-01-10", "2006-01-10", "Robert J Ippolito"], ["python.org", "1995-03-27", "2007-03-28", "Python Software Foundation"] ] } MochiKit-1.4.2/examples/ajax_tables/ajax_tables.css0000660000175000017500000000261011102215706021351 0ustar scottscotth1 { font-size: 2em; color: #4B4545; text-align: center; } table.datagrid { width: 100%; border-collapse: collapse; } table.datagrid thead th { text-align: left; background-color: #4B4545; background-repeat: no-repeat; background-position: right center; color: white; font-weight: bold; padding: .3em .7em; font-size: .9em; padding-right: 5px; background-repeat: no-repeat; background-position: 95% right; } table.datagrid thead th a { color: white; text-decoration: none; font-size: 1.0em; background-repeat: no-repeat; background-position: center right; padding-right: 15px; } table.datagrid thead th.over { background-color: #746B6B; cursor: pointer; } table.datagrid tbody th { font-weight: bold; } table.datagrid tbody td, table.datagrid tbody th { text-align: left; padding: .3em .7em; border-bottom: 1px solid #eee; } table.datagrid tbody tr.alternate td, table.datagrid tbody tr.alternate th { background-color: #f1f1f1; } table.datagrid tfoot td, table.datagrid tfoot th { background-color: #FFFEE3; color: #4B4545; padding: .5em; font-weight: bold; border-top: 2px solid #4B4545; } table.datagrid tfoot th { text-align: left; } table.datagrid tfoot td { } .invisible { display: none; } .mochi-template { display: none; } .mochi-example { display: none; } MochiKit-1.4.2/examples/view-source/0000755000175000017500000000000011136470265016372 5ustar scottscottMochiKit-1.4.2/examples/view-source/view-source.js0000660000175000017500000000374111102215704021167 0ustar scottscott/* Do syntax highlighting on every textarea inside of a "codeview" element The content of textareas are URLs, not code! */ var viewSource = function () { var filename = location.hash; if (!filename) { filename = location.hash = "view-source/view-source.js"; } filename = lstrip(filename, "#"); var href = "../" + filename; replaceChildNodes("filename", "loading ", A({"href": href}, filename)); replaceChildNodes("code", href); ext = filename.split(".").pop(); var classes = { "html": "xml", "js": "javascript", "json": "javascript", "xml": "xml" }; updateNodeAttributes("code", {"class": classes[ext]}); syntaxHighlight(filename); }; var syntaxHighlight = function (filename) { var swapContents = function (dest, req) { replaceChildNodes(dest, req.responseText); }; var showParsing = function () { replaceChildNodes("filename", "parsing ", A({"href": "../" + filename}, filename) ); return wait(0); }; var finishSyntaxHighlight = function () { dp.sh.HighlightAll("code", true, true, false); replaceChildNodes("filename", A({"href": "../" + filename}, filename)); removeElementClass("codeview", "invisible"); }; var elems = getElementsByTagAndClassName("textarea", null, "codeview"); var dl = new Deferred(); var deferredCount = 0; var checkDeferredList = function () { deferredCount -= 1; if (!deferredCount) { dl.callback(); } }; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; if (elem.name != "code") { continue; } var url = strip(scrapeText(elem)) var d = doXHR(url).addCallback( partial(swapContents, elem) ); deferredCount += 1; d.addCallback(checkDeferredList); } dl.addCallback(showParsing); dl.addCallback(finishSyntaxHighlight); }; MochiKit-1.4.2/examples/view-source/view-source.css0000660000175000017500000000003411102215704021333 0ustar scottscott.invisible {display: none;} MochiKit-1.4.2/examples/view-source/view-source.html0000660000175000017500000000172511113647642021533 0ustar scottscott MochiKit Example Source Viewer

MochiKit-1.4.2/examples/view-source/lib/0000755000175000017500000000000011136470265017140 5ustar scottscottMochiKit-1.4.2/examples/view-source/lib/SyntaxHighlighter/0000755000175000017500000000000011136470265022605 5ustar scottscottMochiKit-1.4.2/examples/view-source/lib/SyntaxHighlighter/Tests.html0000660000175000017500000001723111113647642024577 0ustar scottscott dp.SyntaxHighlighter testing

Smart Tabs & First Line

C Sharp

JavaScript

Visual Basic

XML / HTML

PHP

SQL

Delphi

Python

Auto Overflow Test

400px
MochiKit-1.4.2/examples/view-source/lib/SyntaxHighlighter/shBrushPython.js0000660000175000017500000001365611102215704025760 0ustar scottscott/* Python 2.3 syntax contributed by Gheorghe Milas */ dp.sh.Brushes.Python = function() { var keywords = 'and assert break class continue def del elif else except exec ' + 'finally for from global if import in is lambda not or object pass print ' + 'raise return try yield while'; var builtins = 'self __builtin__ __dict__ __future__ __methods__ __members__ __author__ __email__ __version__' + '__class__ __bases__ __import__ __main__ __name__ __doc__ __self__ __debug__ __slots__ ' + 'abs append apply basestring bool buffer callable chr classmethod clear close cmp coerce compile complex ' + 'conjugate copy count delattr dict dir divmod enumerate Ellipsis eval execfile extend False file fileno filter float flush ' + 'get getattr globals has_key hasarttr hash hex id index input insert int intern isatty isinstance isubclass ' + 'items iter keys len list locals long map max min mode oct open ord pop pow property range ' + 'raw_input read readline readlines reduce reload remove repr reverse round seek setattr slice sum ' + 'staticmethod str super tell True truncate tuple type unichr unicode update values write writelines xrange zip'; var magicmethods = '__abs__ __add__ __and__ __call__ __cmp__ __coerce__ __complex__ __concat__ __contains__ __del__ __delattr__ __delitem__ ' + '__delslice__ __div__ __divmod__ __float__ __getattr__ __getitem__ __getslice__ __hash__ __hex__ __eq__ __le__ __lt__ __gt__ __ge__ ' + '__iadd__ __isub__ __imod__ __idiv__ __ipow__ __iand__ __ior__ __ixor__ __ilshift__ __irshift__ ' + '__invert__ __init__ __int__ __inv__ __iter__ __len__ __long__ __lshift__ __mod__ __mul__ __new__ __neg__ __nonzero__ __oct__ __or__ ' + '__pos__ __pow__ __radd__ __rand__ __rcmp__ __rdiv__ __rdivmod__ __repeat__ __repr__ __rlshift__ __rmod__ __rmul__ ' + '__ror__ __rpow__ __rrshift__ __rshift__ __rsub__ __rxor__ __setattr__ __setitem__ __setslice__ __str__ __sub__ __xor__'; var exceptions = 'Exception StandardError ArithmeticError LookupError EnvironmentError AssertionError AttributeError EOFError ' + 'FutureWarning IndentationError OverflowWarning PendingDeprecationWarning ReferenceError RuntimeWarning ' + 'SyntaxWarning TabError UnicodeDecodeError UnicodeEncodeError UnicodeTranslateError UserWarning Warning ' + 'IOError ImportError IndexError KeyError KeyboardInterrupt MemoryError NameError NotImplementedError OSError ' + 'RuntimeError StopIteration SyntaxError SystemError SystemExit TypeError UnboundLocalError UnicodeError ValueError ' + 'FloatingPointError OverflowError WindowsError ZeroDivisionError'; var types = 'NoneType TypeType IntType LongType FloatType ComplexType StringType UnicodeType BufferType TupleType ListType ' + 'DictType FunctionType LambdaType CodeType ClassType UnboundMethodType InstanceType MethodType BuiltinFunctionType BuiltinMethodType ' + 'ModuleType FileType XRangeType TracebackType FrameType SliceType EllipsisType'; var commonlibs = 'anydbm array asynchat asyncore AST base64 binascii binhex bisect bsddb buildtools bz2 ' + 'BaseHTTPServer Bastion calendar cgi cmath cmd codecs codeop commands compiler copy copy_reg ' + 'cPickle crypt cStringIO csv curses Carbon CGIHTTPServer ConfigParser Cookie datetime dbhash ' + 'dbm difflib dircache distutils doctest DocXMLRPCServer email encodings errno exceptions fcntl ' + 'filecmp fileinput ftplib gc gdbm getopt getpass glob gopherlib gzip heapq htmlentitydefs ' + 'htmllib httplib HTMLParser imageop imaplib imgfile imghdr imp inspect itertools jpeg keyword ' + 'linecache locale logging mailbox mailcap marshal math md5 mhlib mimetools mimetypes mimify mmap ' + 'mpz multifile mutex MimeWriter netrc new nis nntplib nsremote operator optparse os parser pickle pipes ' + 'popen2 poplib posix posixfile pprint preferences profile pstats pwd pydoc pythonprefs quietconsole ' + 'quopri Queue random re readline resource rexec rfc822 rgbimg sched select sets sgmllib sha shelve shutil ' + 'signal site smtplib socket stat statcache string struct symbol sys syslog SimpleHTTPServer ' + 'SimpleXMLRPCServer SocketServer StringIO tabnanny tarfile telnetlib tempfile termios textwrap ' + 'thread threading time timeit token tokenize traceback tty types Tkinter unicodedata unittest ' + 'urllib urllib2 urlparse user UserDict UserList UserString warnings weakref webbrowser whichdb ' + 'xml xmllib xmlrpclib xreadlines zipfile zlib'; this.regexList = [ { regex: new RegExp('#.*$', 'gm'), css: 'comment' }, // comments { regex: new RegExp('^\\s*"""(.|\n)*?"""\\s*$', 'gm'), css: 'docstring' }, // documentation string " { regex: new RegExp('^\\s*\'\'\'(.|\n)*?\'\'\'\\s*$', 'gm'), css: 'docstring' }, // documentation string ' { regex: new RegExp('"""(.|\n)*?"""', 'g'), css: 'string' }, // multi-line strings " { regex: new RegExp('\'\'\'(.|\n)*?\'\'\'', 'g'), css: 'string' }, // multi-line strings ' { regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'), css: 'string' }, // strings " { regex: new RegExp('\'(?:\\.|[^\\\'\'])*\'', 'g'), css: 'string' }, // strings ' { regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' }, // keywords { regex: new RegExp(this.GetKeywords(builtins), 'gm'), css: 'builtins' }, // builtin objects, functions, methods, magic attributes { regex: new RegExp(this.GetKeywords(magicmethods), 'gm'), css: 'magicmethods' }, // special methods { regex: new RegExp(this.GetKeywords(exceptions), 'gm'), css: 'exceptions' }, // standard exception classes { regex: new RegExp(this.GetKeywords(types), 'gm'), css: 'types' }, // types from types.py { regex: new RegExp(this.GetKeywords(commonlibs), 'gm'), css: 'commonlibs' } // common standard library modules ]; this.CssClass = 'dp-py'; } dp.sh.Brushes.Python.prototype = new dp.sh.Highlighter(); dp.sh.Brushes.Python.Aliases = ['py', 'python']; MochiKit-1.4.2/examples/view-source/lib/SyntaxHighlighter/shBrushPhp.js0000660000175000017500000000220311102215704025210 0ustar scottscottdp.sh.Brushes.Php = function() { var keywords = 'and or xor __FILE__ __LINE__ array as break case ' + 'cfunction class const continue declare default die do echo else ' + 'elseif empty enddeclare endfor endforeach endif endswitch endwhile eval exit ' + 'extends for foreach function global if include include_once isset list ' + 'new old_function print require require_once return static switch unset use ' + 'var while __FUNCTION__ __CLASS__'; this.regexList = [ { regex: new RegExp('//.*$', 'gm'), css: 'comment' }, // one line comments { regex: new RegExp('/\\*[\\s\\S]*?\\*/', 'g'), css: 'comment' }, // multiline comments { regex: new RegExp('"(?:[^"\n]|[\"])*?"', 'g'), css: 'string' }, // double quoted strings { regex: new RegExp("'(?:[^'\n]|[\'])*?'", 'g'), css: 'string' }, // single quoted strings { regex: new RegExp('\\$\\w+', 'g'), css: 'vars' }, // variables { regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' } // keyword ]; this.CssClass = 'dp-c'; } dp.sh.Brushes.Php.prototype = new dp.sh.Highlighter(); dp.sh.Brushes.Php.Aliases = ['php']; MochiKit-1.4.2/examples/view-source/lib/SyntaxHighlighter/shBrushVb.js0000660000175000017500000000314211102215704025033 0ustar scottscottdp.sh.Brushes.Vb = function() { var keywords = 'AddHandler AddressOf AndAlso Alias And Ansi As Assembly Auto ' + 'Boolean ByRef Byte ByVal Call Case Catch CBool CByte CChar CDate ' + 'CDec CDbl Char CInt Class CLng CObj Const CShort CSng CStr CType ' + 'Date Decimal Declare Default Delegate Dim DirectCast Do Double Each ' + 'Else ElseIf End Enum Erase Error Event Exit False Finally For Friend ' + 'Function Get GetType GoSub GoTo Handles If Implements Imports In ' + 'Inherits Integer Interface Is Let Lib Like Long Loop Me Mod Module ' + 'MustInherit MustOverride MyBase MyClass Namespace New Next Not Nothing ' + 'NotInheritable NotOverridable Object On Option Optional Or OrElse ' + 'Overloads Overridable Overrides ParamArray Preserve Private Property ' + 'Protected Public RaiseEvent ReadOnly ReDim REM RemoveHandler Resume ' + 'Return Select Set Shadows Shared Short Single Static Step Stop String ' + 'Structure Sub SyncLock Then Throw To True Try TypeOf Unicode Until ' + 'Variant When While With WithEvents WriteOnly Xor'; this.regexList = [ { regex: new RegExp('\'.*$', 'gm'), css: 'comment' }, // one line comments { regex: new RegExp('"(?:\\.|[^\\""])*"', 'g'), css: 'string' }, // strings { regex: new RegExp('^\\s*#.*', 'gm'), css: 'preprocessor' }, // preprocessor tags like #region and #endregion { regex: new RegExp(this.GetKeywords(keywords), 'gm'), css: 'keyword' } // c# keyword ]; this.CssClass = 'dp-vb'; } dp.sh.Brushes.Vb.prototype = new dp.sh.Highlighter(); dp.sh.Brushes.Vb.Aliases = ['vb', 'vb.net']; MochiKit-1.4.2/examples/view-source/lib/SyntaxHighlighter/shCore.js0000660000175000017500000003734611102215704024365 0ustar scottscott/** * Code Syntax Highlighter. * Version 1.3.0 * Copyright (C) 2004 Alex Gorbatchev. * http://www.dreamprojections.com/syntaxhighlighter/ * * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General * Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // // create namespaces // var dp = { sh : // dp.sh { Utils : {}, // dp.sh.Utils Brushes : {}, // dp.sh.Brushes Strings : {}, Version : '1.3.0' } }; dp.sh.Strings = { AboutDialog : 'About...

dp.SyntaxHighlighter

Version: {V}

http://www.dreamprojections.com/SyntaxHighlighter

©2004-2005 Alex Gorbatchev. All right reserved.
', // tools ExpandCode : '+ expand code', ViewPlain : 'view plain', Print : 'print', CopyToClipboard : 'copy to clipboard', About : '?', CopiedToClipboard : 'The code is in your clipboard now.' }; dp.SyntaxHighlighter = dp.sh; // // Dialog and toolbar functions // dp.sh.Utils.Expand = function(sender) { var table = sender; var span = sender; // find the span in which the text label and pipe contained so we can hide it while(span != null && span.tagName.toUpperCase() != 'SPAN') span = span.parentNode; // find the table while(table != null && table.tagName.toUpperCase() != 'TABLE') table = table.parentNode; // remove the 'expand code' button span.parentNode.removeChild(span); table.tBodies[0].className = 'show'; table.parentNode.style.height = '100%'; // containing div isn't getting updated properly when the TBODY is shown } // opens a new windows and puts the original unformatted source code inside. dp.sh.Utils.ViewSource = function(sender) { var code = sender.parentNode.originalCode; var wnd = window.open('', '_blank', 'width=750, height=400, location=0, resizable=1, menubar=0, scrollbars=1'); code = code.replace(/' + code + ''); wnd.document.close(); } // copies the original source code in to the clipboard (IE only) dp.sh.Utils.ToClipboard = function(sender) { var code = sender.parentNode.originalCode; // This works only for IE. There's a way to make it work with Mozilla as well, // but it requires security settings changed on the client, which isn't by // default, so 99% of users won't have it working anyways. if(window.clipboardData) { window.clipboardData.setData('text', code); alert(dp.sh.Strings.CopiedToClipboard); } } // creates an invisible iframe, puts the original source code inside and prints it dp.sh.Utils.PrintSource = function(sender) { var td = sender.parentNode; var code = td.processedCode; var iframe = document.createElement('IFRAME'); var doc = null; var wnd = // this hides the iframe iframe.style.cssText = 'position:absolute; width:0px; height:0px; left:-5px; top:-5px;'; td.appendChild(iframe); doc = iframe.contentWindow.document; code = code.replace(/' + code + ''); doc.close(); iframe.contentWindow.focus(); iframe.contentWindow.print(); td.removeChild(iframe); } dp.sh.Utils.About = function() { var wnd = window.open('', '_blank', 'dialog,width=320,height=150,scrollbars=0'); var doc = wnd.document; var styles = document.getElementsByTagName('style'); var links = document.getElementsByTagName('link'); doc.write(dp.sh.Strings.AboutDialog.replace('{V}', dp.sh.Version)); // copy over ALL the styles from the parent page for(var i = 0; i < styles.length; i++) doc.write(''); for(var i = 0; i < links.length; i++) if(links[i].rel.toLowerCase() == 'stylesheet') doc.write(''); doc.close(); wnd.focus(); } // // Match object // dp.sh.Match = function(value, index, css) { this.value = value; this.index = index; this.length = value.length; this.css = css; } // // Highlighter object // dp.sh.Highlighter = function() { this.addGutter = true; this.addControls = true; this.collapse = false; this.tabsToSpaces = true; } // static callback for the match sorting dp.sh.Highlighter.SortCallback = function(m1, m2) { // sort matches by index first if(m1.index < m2.index) return -1; else if(m1.index > m2.index) return 1; else { // if index is the same, sort by length if(m1.length < m2.length) return -1; else if(m1.length > m2.length) return 1; } return 0; } // gets a list of all matches for a given regular expression dp.sh.Highlighter.prototype.GetMatches = function(regex, css) { var index = 0; var match = null; while((match = regex.exec(this.code)) != null) { this.matches[this.matches.length] = new dp.sh.Match(match[0], match.index, css); } } dp.sh.Highlighter.prototype.AddBit = function(str, css) { var span = document.createElement('span'); str = str.replace(/&/g, '&'); str = str.replace(/ /g, ' '); str = str.replace(/'); // when adding a piece of code, check to see if it has line breaks in it // and if it does, wrap individual line breaks with span tags if(css != null) { var regex = new RegExp('
', 'gi'); if(regex.test(str)) { var lines = str.split(' 
'); str = ''; for(var i = 0; i < lines.length; i++) { span = document.createElement('SPAN'); span.className = css; span.innerHTML = lines[i]; this.div.appendChild(span); // don't add a
for the last line if(i + 1 < lines.length) this.div.appendChild(document.createElement('BR')); } } else { span.className = css; span.innerHTML = str; this.div.appendChild(span); } } else { span.innerHTML = str; this.div.appendChild(span); } } // checks if one match is inside any other match dp.sh.Highlighter.prototype.IsInside = function(match) { if(match == null || match.length == 0) return; for(var i = 0; i < this.matches.length; i++) { var c = this.matches[i]; if(c == null) continue; if((match.index > c.index) && (match.index <= c.index + c.length)) return true; } return false; } dp.sh.Highlighter.prototype.ProcessRegexList = function() { for(var i = 0; i < this.regexList.length; i++) this.GetMatches(this.regexList[i].regex, this.regexList[i].css); } dp.sh.Highlighter.prototype.ProcessSmartTabs = function(code) { var lines = code.split('\n'); var result = ''; var tabSize = 4; var tab = '\t'; // This function inserts specified amount of spaces in the string // where a tab is while removing that given tab. function InsertSpaces(line, pos, count) { var left = line.substr(0, pos); var right = line.substr(pos + 1, line.length); // pos + 1 will get rid of the tab var spaces = ''; for(var i = 0; i < count; i++) spaces += ' '; return left + spaces + right; } // This function process one line for 'smart tabs' function ProcessLine(line, tabSize) { if(line.indexOf(tab) == -1) return line; var pos = 0; while((pos = line.indexOf(tab)) != -1) { // This is pretty much all there is to the 'smart tabs' logic. // Based on the position within the line and size of a tab, // calculate the amount of spaces we need to insert. var spaces = tabSize - pos % tabSize; line = InsertSpaces(line, pos, spaces); } return line; } // Go through all the lines and do the 'smart tabs' magic. for(var i = 0; i < lines.length; i++) result += ProcessLine(lines[i], tabSize) + '\n'; return result; } dp.sh.Highlighter.prototype.SwitchToTable = function() { // thanks to Lachlan Donald from SitePoint.com for this
tag fix. var html = this.div.innerHTML.replace(/<(br)\/?>/gi, '\n'); var lines = html.split('\n'); var row = null; var cell = null; var tBody = null; var html = ''; var pipe = ' | '; // creates an anchor to a utility function UtilHref(util, text) { return '' + text + ''; } tBody = document.createElement('TBODY'); // can be created and all others go to tBodies collection. this.table.appendChild(tBody); if(this.addGutter == true) { row = tBody.insertRow(-1); cell = row.insertCell(-1); cell.className = 'tools-corner'; } if(this.addControls == true) { var tHead = document.createElement('THEAD'); // controls will be placed in here this.table.appendChild(tHead); row = tHead.insertRow(-1); // add corner if there's a gutter if(this.addGutter == true) { cell = row.insertCell(-1); cell.className = 'tools-corner'; } cell = row.insertCell(-1); // preserve some variables for the controls cell.originalCode = this.originalCode; cell.processedCode = this.code; cell.className = 'tools'; if(this.collapse == true) { tBody.className = 'hide'; cell.innerHTML += '' + UtilHref('Expand', dp.sh.Strings.ExpandCode) + '' + pipe + ''; } cell.innerHTML += UtilHref('ViewSource', dp.sh.Strings.ViewPlain) + pipe + UtilHref('PrintSource', dp.sh.Strings.Print); // IE has this clipboard object which is easy enough to use if(window.clipboardData) cell.innerHTML += pipe + UtilHref('ToClipboard', dp.sh.Strings.CopyToClipboard); cell.innerHTML += pipe + UtilHref('About', dp.sh.Strings.About); } for(var i = 0, lineIndex = this.firstLine; i < lines.length - 1; i++, lineIndex++) { row = tBody.insertRow(-1); if(this.addGutter == true) { cell = row.insertCell(-1); cell.className = 'gutter'; cell.innerHTML = lineIndex; } cell = row.insertCell(-1); cell.className = 'line' + (i % 2 + 1); // uses .line1 and .line2 css styles for alternating lines cell.innerHTML = lines[i]; } this.div.innerHTML = ''; } dp.sh.Highlighter.prototype.Highlight = function(code) { function Trim(str) { return str.replace(/^\s*(.*?)[\s\n]*$/g, '$1'); } function Chop(str) { return str.replace(/\n*$/, '').replace(/^\n*/, ''); } function Unindent(str) { var lines = str.split('\n'); var indents = new Array(); var regex = new RegExp('^\\s*', 'g'); var min = 1000; // go through every line and check for common number of indents for(var i = 0; i < lines.length && min > 0; i++) { if(Trim(lines[i]).length == 0) continue; var matches = regex.exec(lines[i]); if(matches != null && matches.length > 0) min = Math.min(matches[0].length, min); } // trim minimum common number of white space from the begining of every line if(min > 0) for(var i = 0; i < lines.length; i++) lines[i] = lines[i].substr(min); return lines.join('\n'); } // This function returns a portions of the string from pos1 to pos2 inclusive function Copy(string, pos1, pos2) { return string.substr(pos1, pos2 - pos1); } var pos = 0; this.originalCode = code; this.code = Chop(Unindent(code)); this.div = document.createElement('DIV'); this.table = document.createElement('TABLE'); this.matches = new Array(); if(this.CssClass != null) this.table.className = this.CssClass; // replace tabs with spaces if(this.tabsToSpaces == true) this.code = this.ProcessSmartTabs(this.code); this.table.border = 0; this.table.cellSpacing = 0; this.table.cellPadding = 0; this.ProcessRegexList(); // if no matches found, add entire code as plain text if(this.matches.length == 0) { this.AddBit(this.code, null); this.SwitchToTable(); return; } // sort the matches this.matches = this.matches.sort(dp.sh.Highlighter.SortCallback); // The following loop checks to see if any of the matches are inside // of other matches. This process would get rid of highligting strings // inside comments, keywords inside strings and so on. for(var i = 0; i < this.matches.length; i++) if(this.IsInside(this.matches[i])) this.matches[i] = null; // Finally, go through the final list of matches and pull the all // together adding everything in between that isn't a match. for(var i = 0; i < this.matches.length; i++) { var match = this.matches[i]; if(match == null || match.length == 0) continue; this.AddBit(Copy(this.code, pos, match.index), null); this.AddBit(match.value, match.css); pos = match.index + match.length; } this.AddBit(this.code.substr(pos), null); this.SwitchToTable(); } dp.sh.Highlighter.prototype.GetKeywords = function(str) { return '\\b' + str.replace(/ /g, '\\b|\\b') + '\\b'; } // highlightes all elements identified by name and gets source code from specified property dp.sh.HighlightAll = function(name, showGutter /* optional */, showControls /* optional */, collapseAll /* optional */, firstLine /* optional */) { function FindValue() { var a = arguments; for(var i = 0; i < a.length; i++) { if(a[i] == null) continue; if(typeof(a[i]) == 'string' && a[i] != '') return a[i] + ''; if(typeof(a[i]) == 'object' && a[i].value != '') return a[i].value + ''; } return null; } function IsOptionSet(value, list) { for(var i = 0; i < list.length; i++) if(list[i] == value) return true; return false; } function GetOptionValue(name, list, defaultValue) { var regex = new RegExp('^' + name + '\\[(\\w+)\\]$', 'gi'); var matches = null; for(var i = 0; i < list.length; i++) if((matches = regex.exec(list[i])) != null) return matches[1]; return defaultValue; } var elements = document.getElementsByName(name); var highlighter = null; var registered = new Object(); var propertyName = 'value'; // if no code blocks found, leave if(elements == null) return; // register all brushes for(var brush in dp.sh.Brushes) { var aliases = dp.sh.Brushes[brush].Aliases; if(aliases == null) continue; for(var i = 0; i < aliases.length; i++) registered[aliases[i]] = brush; } for(var i = 0; i < elements.length; i++) { var element = elements[i]; var options = FindValue( element.attributes['class'], element.className, element.attributes['language'], element.language ); var language = ''; if(options == null) continue; options = options.split(':'); language = options[0].toLowerCase(); if(registered[language] == null) continue; // instantiate a brush highlighter = new dp.sh.Brushes[registered[language]](); // hide the original element element.style.display = 'none'; highlighter.addGutter = (showGutter == null) ? !IsOptionSet('nogutter', options) : showGutter; highlighter.addControls = (showControls == null) ? !IsOptionSet('nocontrols', options) : showControls; highlighter.collapse = (collapseAll == null) ? IsOptionSet('collapse', options) : collapseAll; // first line idea comes from Andrew Collington, thanks! highlighter.firstLine = (firstLine == null) ? parseInt(GetOptionValue('firstline', options, 1)) : firstLine; highlighter.Highlight(element[propertyName]); // place the result table inside a div var div = document.createElement('DIV'); div.className = 'dp-highlighter'; div.appendChild(highlighter.table); element.parentNode.insertBefore(div, element); } } MochiKit-1.4.2/examples/view-source/lib/SyntaxHighlighter/SyntaxHighlighter.css0000660000175000017500000000675111102215704026757 0ustar scottscott /* Main style for the table */ .dp-highlighter { width: 100%; overflow: auto; line-height: 100% !important; margin: 18px 0px 18px 0px; } .dp-highlighter table { width: 100%; margin: 2px 0px 2px 0px; border-collapse: collapse; border-bottom: 2px solid #eee; background-color: #fff; } .dp-highlighter tbody.hide { display: none; } .dp-highlighter tbody.show { display: table-row-group; _display: block; } .dp-highlighter td { font-family: Courier New; font-size: 11px; } /* Styles for the tools */ .dp-highlighter .tools-corner { background-color: #eee; font-size: 9px; } .dp-highlighter .tools { background-color: #eee; padding: 3px 8px 3px 10px; border-bottom: 1px solid gray; font: 9px Verdana, Geneva, Arial, Helvetica, sans-serif; color: silver; } .dp-highlighter .tools-corner { background-color: #eee; } .dp-highlighter .tools a { font-size: 9px; color: gray; text-decoration: none; } .dp-highlighter .tools a:hover { color: red; text-decoration: underline; } /* Gutter with line number */ .dp-highlighter .gutter { padding-right: 5px; padding-left: 10px; width: 5px; background-color: #eee; border-right: 1px solid gray; color: gray; text-align: right; vertical-align: top; } /* Single line style */ .dp-highlighter .line1, .line2 { padding-left: 10px; border-bottom: 1px solid #F7F7F7; white-space:nowrap; } .dp-highlighter .line2 { background-color: #F7F7F7; } /* About dialog styles */ .dp-about { background-color: #fff; margin: 0px; } .dp-about table { width: 100%; height: 100%; font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; } .dp-about td { padding: 10px; vertical-align: top; } .dp-about .copy { border-bottom: 1px solid #ACA899; height: 95%; } .dp-about .title { color: red; font-weight: bold; } .dp-about .para { margin-bottom: 4px; } .dp-about .footer { background-color: #ECEADB; border-top: 1px solid #fff; text-align: right; } .dp-about .close { font-size: 11px; font-family: Tahoma, Verdana, Arial, sans-serif !important; background-color: #ECEADB; width: 60px; height: 22px; } /* Language specific styles */ .dp-c {} .dp-c .comment { color: green; } .dp-c .string { color: blue; } .dp-c .preprocessor { color: gray; } .dp-c .keyword { color: blue; } .dp-c .vars { color: #d00; } .dp-vb {} .dp-vb .comment { color: green; } .dp-vb .string { color: blue; } .dp-vb .preprocessor { color: gray; } .dp-vb .keyword { color: blue; } .dp-sql {} .dp-sql .comment { color: green; } .dp-sql .string { color: red; } .dp-sql .keyword { color: blue; } .dp-sql .func { color: #ff1493; } .dp-sql .op { color: #808080; } .dp-xml {} .dp-xml .cdata { color: #ff1493; } .dp-xml .comments { color: green; } .dp-xml .tag { color: blue; } .dp-xml .tag-name { color: black; font-weight: bold; } .dp-xml .attribute { color: red; } .dp-xml .attribute-value { color: blue; } .dp-delphi {} .dp-delphi .comment { color: #008200; font-style: italic; } .dp-delphi .string { color: blue; } .dp-delphi .number { color: blue; } .dp-delphi .directive { color: #008284; } .dp-delphi .keyword { font-weight: bold; color: navy; } .dp-delphi .vars { color: #000; } .dp-py {} .dp-py .comment { color: green; } .dp-py .string { color: red; } .dp-py .docstring { color: brown; } .dp-py .keyword { color: blue; font-weight: bold;} .dp-py .builtins { color: #ff1493; } .dp-py .magicmethods { color: #808080; } .dp-py .exceptions { color: brown; } .dp-py .types { color: brown; font-style: italic; } .dp-py .commonlibs { color: #8A2BE2; font-style: italic; } MochiKit-1.4.2/examples/view-source/lib/SyntaxHighlighter/shBrushCSharp.js0000660000175000017500000000354011102215704025646 0ustar scottscottdp.sh.Brushes.CSharp = function() { var keywords = 'abstract as base bool break byte case catch char checked class const ' + 'continue decimal default delegate do double else enum event explicit ' + 'extern false finally fixed float for foreach get goto if implicit in int ' + 'interface internal is lock long namespace new null object operator out ' + 'override params private protected public readonly ref return sbyte sealed set ' + 'short sizeof stackalloc static string struct switch this throw true try ' + 'typeof uint ulong unchecked unsafe ushort using virtual void while'; this.regexList = [ // There's a slight problem with matching single line comments and figuring out // a difference between // and ///. Using lookahead and lookbehind solves the // problem, unfortunately JavaScript doesn't support lookbehind. So I'm at a // loss how to translate that regular expression to JavaScript compatible one. // { regex: new RegExp('(?) | () | (<)*(\w+)*\s*(\w+)\s*=\s*(".*?"|'.*?'|\w+)(/*>)* | () */ var index = 0; var match = null; var regex = null; // Match CDATA in the following format // <\!\[[\w\s]*?\[(.|\s)*?\]\]> this.GetMatches(new RegExp('<\\!\\[[\\w\\s]*?\\[(.|\\s)*?\\]\\]>', 'gm'), 'cdata'); // Match comments // this.GetMatches(new RegExp('', 'gm'), 'comments'); // Match attributes and their values // (\w+)\s*=\s*(".*?"|\'.*?\'|\w+)* regex = new RegExp('([\\w-\.]+)\\s*=\\s*(".*?"|\'.*?\'|\\w+)*', 'gm'); while((match = regex.exec(this.code)) != null) { push(this.matches, new dp.sh.Match(match[1], match.index, 'attribute')); // if xml is invalid and attribute has no property value, ignore it if(match[2] != undefined) { push(this.matches, new dp.sh.Match(match[2], match.index + match[0].indexOf(match[2]), 'attribute-value')); } } // Match opening and closing tag brackets // this.GetMatches(new RegExp('', 'gm'), 'tag'); // Match tag names // MochiRegExp - JavaScript Regular Expression (RegExp) Explorer

MochiRegExp - JavaScript Regular Expression (RegExp) Explorer

This demo does "live" Regular Expression matching to help you toy with JavaScript Regular Expressions. It takes advantage of MochiKit's MochiKit.DOM to manipulate the display and MochiKit.Async to facilitate the "half a second" live updating.

The table will update while you're typing if you're idle for half a second or when you tab away from the field, whichever comes first. If you enter an invalid RegExp, the RegExp label will turn red (the "error" class). For a good JavaScript's RegExp reference, see Regular Expressions over at DevMo.

View Source: [ index.html | mochiregexp.js ]
Property Result Repr
MochiKit-1.4.2/examples/interpreter/0000755000175000017500000000000011136470264016464 5ustar scottscottMochiKit-1.4.2/examples/interpreter/interpreter.js0000660000175000017500000002502311102215702021350 0ustar scottscott/* Interpreter: JavaScript Interactive Interpreter */ InterpreterManager = function () { bindMethods(this); }; InterpreterManager.prototype.initialize = function () { connect("interpreter_text", "onkeyup", this.keyUp); connect("interpreter_textarea", "onkeydown", this.areaKeyDown); connect("interpreter_form", "onsubmit", this.submit); getElement("interpreter_text").focus(); this.banner(); this.lines = []; this.history = []; this.currentHistory = ""; this.historyPos = -1; this.blockingOn = null; if (typeof(this.doEval) == "undefined") { // detect broken eval, warn at some point if a namespace ever gets used this.doEval = function () { return eval(arguments[0]); } } window.help = this.help; this.help.NAME = 'type help(func) for help on a MochiKit function'; }; InterpreterManager.prototype.banner = function () { var _ua = window.navigator.userAgent; var ua = _ua.replace(/^Mozilla\/.*?\(.*?\)\s*/, ""); if (ua == "") { // MSIE ua = _ua.replace(/^Mozilla\/4\.0 \(compatible; MS(IE .*?);.*$/, "$1"); } appendChildNodes("interpreter_output", SPAN({"class": "banner"}, "MochiKit v" + MochiKit.Base.VERSION + " [" + ua + "]", BR(), "Type your expression in the input box below and press return, or see the notes below for more information.", BR() ), BR() ); }; InterpreterManager.prototype.submit = function (event) { if (this.blockingOn) { try { this.blockingOn.cancel(); } catch (e) { this.showError(e); } this.blockingOn = null; } this.doSubmit(); this.doScroll(); event.stop(); }; InterpreterManager.prototype.help = function (fn) { if (fn && fn.NAME) { fn = fn.NAME; } if (typeof(fn) != "string" || fn.length == 0) { writeln("help(func) on any MochiKit function for help"); return; } var comps = fn.split('.'); var base = comps.splice(0, 2); var shortfn = comps.join('.'); var url = '../../doc/html/' + base.join('/') + '.html'; var d = doXHR(url, {mimeType: 'text/xml'}); d.addCallback(function (req) { var els = getElementsByTagAndClassName( 'a', 'mochidef', req.responseXML); var match = '#fn-' + shortfn.toLowerCase(); for (var i = 0; i < els.length; i++) { var elem = els[i]; var href = elem.href; var idx = href.indexOf('#'); if (idx != -1 && href.substring(idx) == match) { writeln(A({href: url + match, target: '_blank'}, scrapeText(elem))); return; } } writeln('documentation for ' + fn + ' not found'); }); blockOn(d); }; InterpreterManager.prototype.doScroll = function () { var p = getElement("interpreter_output").lastChild; if (typeof(p) == "undefined" || p == null) { return; } var area = getElement("interpreter_area"); if (area.offsetHeight > area.scrollHeight) { area.scrollTop = 0; } else { area.scrollTop = area.scrollHeight; } }; InterpreterManager.prototype.moveHistory = function (dir) { // totally bogus value if (dir == 0 || this.history.length == 0) { return; } var elem = getElement("interpreter_text"); if (this.historyPos == -1) { this.currentHistory = elem.value; if (dir > 0) { return; } this.historyPos = this.history.length - 1; elem.value = this.history[this.historyPos]; return; } if (this.historyPos == 0 && dir < 0) { return; } if (this.historyPos == this.history.length - 1 && dir > 0) { this.historyPos = -1; elem.value = this.currentHistory; return; } this.historyPos += dir; elem.value = this.history[this.historyPos]; } InterpreterManager.prototype.runMultipleLines = function (text) { var lines = rstrip(text).replace("\r\n", "\n").split(/\n/); appendChildNodes("interpreter_output", SPAN({"class": "code"}, ">>> ", izip(lines, imap(BR, cycle([null])))) ); this.runCode(text); } InterpreterManager.prototype.areaKeyDown = function (e) { var mod = e.modifier(); var hasMod = mod.alt || mod.ctrl || mod.meta; if (e.key().string == 'KEY_ENTER' && hasMod) { var elem = getElement("interpreter_textarea"); var text = elem.value; elem.value = ""; this.runMultipleLines(text); e.stop(); } }; InterpreterManager.prototype.keyUp = function (e) { var key = e.key(); // if any meta key is pressed, don't handle the signal if (e.modifier().any) { return; } switch (key.string) { case 'KEY_ARROW_UP': this.moveHistory(-1); break; case 'KEY_ARROW_DOWN': this.moveHistory(1); break; default: return; } e.stop(); }; InterpreterManager.prototype.blockOn = function (d) { var node = SPAN({"class": "banner"}, "blocking on " + repr(d) + "..."); this.blockingOn = d; appendChildNodes("interpreter_output", node); this.doScroll(); d.addBoth(function (res) { swapDOM(node); this.blockingOn = null; if (res instanceof CancelledError) { window.writeln(SPAN({"class": "error"}, repr(d) + " cancelled!")); return undefined; } return res; }); d.addCallbacks(this.showResult, this.showError); }; InterpreterManager.prototype.showError = function (e) { if (typeof(e) != "object") { e = new Error(e); } appendChildNodes("interpreter_output", SPAN({"class": "error"}, "Error:"), TABLE({"class": "error"}, THEAD({"class": "invisible"}, TD({"colspan": 2})), TFOOT({"class": "invisible"}, TD({"colspan": 2})), TBODY(null, map(function (kv) { var v = kv[1]; if (typeof(v) == "function") { return; } if (typeof(v) == "object") { v = repr(v); } return TR(null, TD({"class": "error"}, kv[0]), TD({"class": "data"}, v) ); }, sorted(items(e))) ) ) ); window.last_exc = e; this.doScroll(); }; EvalFunctions = { evalWith: function () { with (arguments[1] || window) { return eval(arguments[0]); }; }, evalCall: function () { return eval.call(arguments[1] || window, arguments[0]); }, choose: function () { var ns = {__test__: this}; var e; try { if (this.evalWith("return __test__", ns) === this) { return this.evalWith; } } catch (e) { // pass } try { if (this.evalCall("return __test__", ns) === this) { return this.evalCall; } } catch (e) { // pass } return undefined; } }; InterpreterManager.prototype.doEval = EvalFunctions.choose(); InterpreterManager.prototype.doSubmit = function () { var elem = getElement("interpreter_text"); var code = elem.value; elem.value = ""; var isContinuation = false; if (code.length >= 2 && code.lastIndexOf("//") == code.length - 2) { isContinuation = true; code = code.substr(0, code.length - 2); } appendChildNodes("interpreter_output", SPAN({"class": "code"}, ">>> ", code), BR() ); this.lines.push(code); this.history.push(code); this.historyPos = -1; this.currentHistory = ""; if (isContinuation) { return; } var allCode = this.lines.join("\n"); this.lines = []; this.runCode(allCode); return; }; InterpreterManager.prototype.runCode = function (allCode) { var res; try { res = this.doEval(allCode); } catch (e) { // mozilla shows some keys more than once! this.showError(e); return; } this.showResult(res); }; InterpreterManager.prototype.showResult = function (res) { if (typeof(res) != "undefined") { window._ = res; } if (typeof(res) != "undefined") { appendChildNodes("interpreter_output", SPAN({"class": "data"}, repr(res)), BR() ); this.doScroll(); } }; window.writeln = function () { appendChildNodes("interpreter_output", SPAN({"class": "data"}, arguments), BR() ); interpreterManager.doScroll(); }; window.clear = function () { replaceChildNodes("interpreter_output"); getElement("interpreter_area").scrollTop = 0; }; window.blockOn = function (d) { if (!(d instanceof Deferred)) { throw new TypeError(repr(d) + " is not a Deferred!"); } interpreterManager.blockOn(d); }; window.dir = function (o) { // Python muscle memory! return sorted(keys(o)); }; window.inspect = function (o) { window._ = o; if ((typeof(o) != "function" && typeof(o) != "object") || o == null) { window.writeln(repr(o)); return; } var pairs = items(o); if (pairs.length == 0) { window.writeln(repr(o)); return; } window.writeln(TABLE({"border": "1"}, THEAD({"class": "invisible"}, TR(null, TD(), TD())), TFOOT({"class": "invisible"}, TR(null, TD(), TD())), TBODY(null, map( function (kv) { var click = function () { try { window.inspect(kv[1]); } catch (e) { interpreterManager.showError(e); } return false; } return TR(null, TD(null, A({href: "#", onclick: click}, kv[0])), TD(null, repr(kv[1])) ); }, pairs ) ) )); }; interpreterManager = new InterpreterManager(); addLoadEvent(interpreterManager.initialize); // rewrite the view-source links addLoadEvent(function () { var elems = getElementsByTagAndClassName("A", "view-source"); var page = "interpreter/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } }); MochiKit-1.4.2/examples/interpreter/interpreter.css0000660000175000017500000000224611102215702021526 0ustar scottscotth1 { font-size: 2em; color: #4B4545; text-align: center; } textarea.textbox { font-family: Monaco, "lucida console", Courier; border: 1px solid #CCCCCC; font-size: .60em; padding: 2px 4px; margin-top: .3em; } input.textbox { font-family: Monaco, "lucida console", Courier; border: 1px solid #CCCCCC; font-size: .60em; padding: 2px 4px; margin-top: .3em; } #interpreter_area { display: block; border: 1px solid #CCCCCC; padding: 2px 4px; margin-top: .3em; width: 600px; height: 300px; overflow: auto; } #interpreter_output { display: inline; font-family: Monaco, "lucida console", Courier; font-size: .60em; } #interpreter_output span { white-space: -moz-pre-wrap; /* Mozilla */ white-space: -o-pre-wrap; /* Opera 7 */ white-space: pre-wrap; /* CSS 2.1 */ white-space: pre-line; /* CSS 3 (and 2.1 as well, actually) */ word-wrap: break-word; /* IE */ wrap-option: emergency; /* CSS 3 */ } input.textbox:focus { background-color: #FFFEE3; } .code { color: blue; } .data { color: black; } .error { color: red; } .banner { color: green; } .invisible { display: none; } MochiKit-1.4.2/examples/interpreter/index.html0000660000175000017500000000735311113647642020470 0ustar scottscott Interpreter - JavaScript Interactive Interpreter

Interpreter - JavaScript Interactive Interpreter

This demo is a JavaScript interpreter. Type some code into the text input and press enter to see the results. It uses MochiKit's MochiKit.DOM to manipulate the display. It also supports waiting for MochiKit.Async Deferreds via blockOn(aDeferred).

View Source: [ index.html | interpreter.js ]

Notes:
  • To show the signature of a MochiKit function and link to its documentation, type help(fn) on any MochiKit function.
  • To write multi-line code snippets, use the lower text area and press ctrl-enter or cmd-enter to submit.
  • function name() {} syntax might not end up in window scope, so use name = function () {} syntax instead
  • If you want to stuff something into the output window other than the repr(...) of the expression result, use the writeln(...) function. It accepts anything that MochiKit.DOM does, so you can even put styled stuff in there!
  • Use clear() to clear the interpreter window.
  • You can use blockOn(aDeferred) to wait on a Deferred. This expression must be used by itself, so the value must be obtained from _ or last_exc. Typing any expression will cancel the Deferred.
  • Up and down arrow keys work as a rudimentary history
  • _ is the value of the last expression that was not undefined, last_exc is the value of the last unhandled exception.
MochiKit-1.4.2/examples/sortable_tables/0000755000175000017500000000000011136470265017267 5ustar scottscottMochiKit-1.4.2/examples/sortable_tables/sortable_tables.css0000660000175000017500000000250211102215702023125 0ustar scottscotth1 { font-size: 2em; color: #4B4545; text-align: center; } table.datagrid { width: 100%; border-collapse: collapse; } table.datagrid thead th { text-align: left; background-color: #4B4545; background-repeat: no-repeat; background-position: right center; color: white; font-weight: bold; padding: .3em .7em; font-size: .9em; padding-right: 5px; background-repeat: no-repeat; background-position: 95% right; } table.datagrid thead th a { color: white; text-decoration: none; font-size: 1.0em; background-repeat: no-repeat; background-position: center right; padding-right: 15px; } table.datagrid thead th.over { background-color: #746B6B; cursor: pointer; } table.datagrid tbody th { font-weight: bold; } table.datagrid tbody td, table.datagrid tbody th { text-align: left; padding: .3em .7em; border-bottom: 1px solid #eee; } table.datagrid tbody tr.alternate td, table.datagrid tbody tr.alternate th { background-color: #f1f1f1; } table.datagrid tfoot td, table.datagrid tfoot th { background-color: #FFFEE3; color: #4B4545; padding: .5em; font-weight: bold; border-top: 2px solid #4B4545; } table.datagrid tfoot th { text-align: left; } table.datagrid tfoot td { } .invisible { display: none; } MochiKit-1.4.2/examples/sortable_tables/sortable_tables.js0000660000175000017500000001462611102215702022763 0ustar scottscott/* On page load, the SortableManager: - Finds the table by its id (sortable_table). - Parses its thead for columns with a "mochi:format" attribute. - Parses the data out of the tbody based upon information given in the "mochi:format" attribute, and clones the tr elements for later re-use. - Clones the column header th elements for use as a template when drawing sort arrow columns. - Stores away a reference to the tbody, as it will be replaced on each sort. - Performs the first sort. On sort request: - Sorts the data based on the given key and direction - Creates a new tbody from the rows in the new ordering - Replaces the column header th elements with clickable versions, adding an indicator (↑ or ↓) to the most recently sorted column. */ SortableManager = function () { this.thead = null; this.tbody = null; this.columns = []; this.rows = []; this.sortState = {}; this.sortkey = 0; }; mouseOverFunc = function () { addElementClass(this, "over"); }; mouseOutFunc = function () { removeElementClass(this, "over"); }; ignoreEvent = function (ev) { if (ev && ev.preventDefault) { ev.preventDefault(); ev.stopPropagation(); } else if (typeof(event) != 'undefined') { event.cancelBubble = false; event.returnValue = false; } }; update(SortableManager.prototype, { "initWithTable": function (table) { /*** Initialize the SortableManager with a table object ***/ // Ensure that it's a DOM element table = getElement(table); // Find the thead this.thead = table.getElementsByTagName('thead')[0]; // get the mochi:format key and contents for each column header var cols = this.thead.getElementsByTagName('th'); for (var i = 0; i < cols.length; i++) { var node = cols[i]; var attr = null; try { attr = node.getAttribute("mochi:format"); } catch (err) { // pass } var o = node.childNodes; this.columns.push({ "format": attr, "element": node, "proto": node.cloneNode(true) }); } // scrape the tbody for data this.tbody = table.getElementsByTagName('tbody')[0]; // every row var rows = this.tbody.getElementsByTagName('tr'); for (var i = 0; i < rows.length; i++) { // every cell var row = rows[i]; var cols = row.getElementsByTagName('td'); var rowData = []; for (var j = 0; j < cols.length; j++) { // scrape the text and build the appropriate object out of it var cell = cols[j]; var obj = scrapeText(cell); switch (this.columns[j].format) { case 'isodate': obj = isoDate(obj); break; case 'str': break; case 'istr': obj = obj.toLowerCase(); break; // cases for numbers, etc. could be here default: break; } rowData.push(obj); } // stow away a reference to the TR and save it rowData.row = row.cloneNode(true); this.rows.push(rowData); } // do initial sort on first column this.drawSortedRows(this.sortkey, true, false); }, "onSortClick": function (name) { /*** Return a sort function for click events ***/ return method(this, function () { log('onSortClick', name); var order = this.sortState[name]; if (order == null) { order = true; } else if (name == this.sortkey) { order = !order; } this.drawSortedRows(name, order, true); }); }, "drawSortedRows": function (key, forward, clicked) { /*** Draw the new sorted table body, and modify the column headers if appropriate ***/ log('drawSortedRows', key, forward); this.sortkey = key; // sort based on the state given (forward or reverse) var cmp = (forward ? keyComparator : reverseKeyComparator); this.rows.sort(cmp(key)); // save it so we can flip next time this.sortState[key] = forward; // get every "row" element from this.rows and make a new tbody var newBody = TBODY(null, map(itemgetter("row"), this.rows)); // swap in the new tbody this.tbody = swapDOM(this.tbody, newBody); for (var i = 0; i < this.columns.length; i++) { var col = this.columns[i]; var node = col.proto.cloneNode(true); // remove the existing events to minimize IE leaks col.element.onclick = null; col.element.onmousedown = null; col.element.onmouseover = null; col.element.onmouseout = null; // set new events for the new node node.onclick = this.onSortClick(i); node.onmousedown = ignoreEvent; node.onmouseover = mouseOverFunc; node.onmouseout = mouseOutFunc; // if this is the sorted column if (key == i) { // \u2193 is down arrow, \u2191 is up arrow // forward sorts mean the rows get bigger going down var arrow = (forward ? "\u2193" : "\u2191"); // add the character to the column header node.appendChild(SPAN(null, arrow)); if (clicked) { node.onmouseover(); } } // swap in the new th col.element = swapDOM(col.element, node); } } }); sortableManager = new SortableManager(); addLoadEvent(function () { sortableManager.initWithTable('sortable_table'); }); // rewrite the view-source links addLoadEvent(function () { var elems = getElementsByTagAndClassName("A", "view-source"); var page = "sortable_tables/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } }); MochiKit-1.4.2/examples/sortable_tables/index.html0000660000175000017500000000507211113647642021266 0ustar scottscott Sortable Tables from Scratch with MochiKit

Sortable Tables from Scratch with MochiKit

This is an example of how one might do sortable tables in an inobtrusive manner. The data is supplied by the server and is already in the table.

For a detailed description of what happens under the hood, check out sortable_tables.js.

View Source: [ index.html | sortable_tables.js ]

Domain Name Creation Date Expiry Date Organization Name
mochibot.com 2005-02-10 2007-02-10 Jameson Hsu
pythonmac.org 2003-09-24 2006-09-24 Bob Ippolito
undefined.org 2000-01-10 2006-01-10 Robert J Ippolito
python.org 1995-03-27 2007-03-28 Python Software Foundation
MochiKit-1.4.2/examples/rounded_corners/0000755000175000017500000000000011136470265017315 5ustar scottscottMochiKit-1.4.2/examples/rounded_corners/index.html0000660000175000017500000000227511113647642021316 0ustar scottscott Demo of MochiKit Visual Elements

MochiKit.Visual

Rounded Corners

This example demonstrates the rounded corners functionality of MochiKit's MochiKit.Visual.

The heading at the top of this page should have all four corners rounded. The heading for this section should just have the bottom corners rounded.

View Source: MochiKit-1.4.2/examples/rounded_corners/rounded_corners.css0000660000175000017500000000024011102215704023200 0ustar scottscotth1 { background: darkgreen; color: yellow; text-align: center; } h2 { background: darkgreen; color: yellow; padding-top: 0.25em;} .invisible { display: none; } MochiKit-1.4.2/examples/rounded_corners/rounded_corners.js0000660000175000017500000000115611102215704023033 0ustar scottscottvar roundedCornersOnLoad = function () { swapDOM("visual_version", SPAN(null, MochiKit.Visual.VERSION)); roundClass("h1", null); roundClass("h2", null, {corners: "bottom"}); }; addLoadEvent(roundedCornersOnLoad); // rewrite the view-source links addLoadEvent(function () { var elems = getElementsByTagAndClassName("A", "view-source"); var page = "rounded_corners/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } }); MochiKit-1.4.2/examples/mouse_events/0000755000175000017500000000000011136470264016635 5ustar scottscottMochiKit-1.4.2/examples/mouse_events/index.html0000660000175000017500000001036411113647642020635 0ustar scottscott Mouse Events with MochiKit

Mouse Events with MochiKit

For a detailed description of what happens under the hood, check out mouse_events.js.

View Source: [ index.html | mouse_events.js | mouse_events.css ]

Hover, Click, or Scroll In Me:

Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page scrolls!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Scroll Me and then the page does not scroll!
Ignore me I just make the page big enough to require scrollbars.
Ignore me I just make the page big enough to require scrollbars.
Ignore me I just make the page big enough to require scrollbars.
Ignore me I just make the page big enough to require scrollbars.
Ignore me I just make the page big enough to require scrollbars.
Ignore me I just make the page big enough to require scrollbars.
Ignore me I just make the page big enough to require scrollbars.
Ignore me I just make the page big enough to require scrollbars.
Ignore me I just make the page big enough to require scrollbars.
MochiKit-1.4.2/examples/mouse_events/mouse_events.js0000660000175000017500000000343711102215706021703 0ustar scottscott/* Mouse Events: Simple Mouse Scrolling Handlers */ function showMouseEvent(evt) { getElement("show-mouse-event-repr").innerHTML = repr(evt); evt.stop(); }; function stopPageFromScrolling( event ) { var src = event.src(); var scrollTop = src.scrollTop; // While trying to stop scrolling events for IE, found that it // jumped around a bit. The following fudgetFactor is NOT the way // to handle this but was the best I could do with the limited time // I had. var fudgeFactor = /MSIE/.test(navigator.userAgent) ? 25 : 0; // scrolling up if (event.mouse().wheel.y < 0) { // Following test should probably be "if (scrollTop == 0)" which // works in FF but not IE. if (scrollTop <= fudgeFactor) { event.stop(); } } //..scrolling down else { // Following test should be "if (scrollTop == src.scrollHeight - src.clientHeight)", // see comment above. if (src.scrollHeight <= (scrollTop + src.clientHeight + fudgeFactor)) { event.stop(); } } }; function connectEvents(){ connect("show-mouse-event", "onmousemove", showMouseEvent); connect("show-mouse-event", "onmousedown", showMouseEvent); connect("show-mouse-event", "onmouseup", showMouseEvent); connect("show-mouse-event", "onmousewheel", showMouseEvent); connect("no-scroll-page", "onmousewheel", stopPageFromScrolling); }; connect(window, 'onload', function() { connectEvents(); var elems = getElementsByTagAndClassName("A", "view-source"); var page = "mouse_events/"; for (var i = 0; i < elems.length; i++) { var elem = elems[i]; var href = elem.href.split(/\//).pop(); elem.target = "_blank"; elem.href = "../view-source/view-source.html#" + page + href; } }); MochiKit-1.4.2/examples/mouse_events/mouse_events.css0000660000175000017500000000040611102215706022050 0ustar scottscotth1 { font-size: 2em; color: #4B4545; text-align: center; } div.scroll-box { border : 2px solid blue; padding : 4ex 4em; margin : 4ex 4em; } div.padding { padding : 4ex 4em; margin : 4ex 4em; border : 1px solid silver; } MochiKit-1.4.2/examples/dnd_sortable/0000755000175000017500000000000011136470264016561 5ustar scottscottMochiKit-1.4.2/examples/dnd_sortable/dnd_sortable.css0000660000175000017500000000051011102215702021710 0ustar scottscotth1 { font-size: 2em; color: #4B4545; text-align: center; } #dnd_sortable { margin: 0; margin-top: 10px; padding: 0; list-style-type: none; width: 250px; } #dnd_sortable li { margin: 0; margin-bottom: 4px; padding: 5px; border: 1px solid #888; cursor: move; text-align: center; } MochiKit-1.4.2/examples/dnd_sortable/sortable_tree_test.html0000660000175000017500000001447211113647642023347 0ustar scottscott Sortable tree test serialize 1 MochiKit-1.4.2/examples/dnd_sortable/sortable5_test.html0000660000175000017500000000177611113647642022420 0ustar scottscott MochiKit sortable functional test file
MochiKit-1.4.2/examples/dnd_sortable/dropmarker.png0000660000175000017500000000032511102215702021416 0ustar scottscottPNG  IHDR%gAMAOX2tEXtSoftwareAdobe ImageReadyqe<PLTE???΀v;tRNS7IDATxց 0APuFF案#Qٍ"Doμ;\/6UUIENDB`MochiKit-1.4.2/examples/dnd_sortable/index.html0000660000175000017500000000375411113647642020566 0ustar scottscott Drag and Drop Sortable Tables with MochiKit

Drag and Drop Sortable Tables with MochiKit

View Source: [ index.html ]

Validate order choice

MochiKit-1.4.2/examples/dnd_sortable/sortable_test.html0000660000175000017500000000322711113647642022324 0ustar scottscott script.aculo.us sortable functional test file Create sortable | Destroy sortable | Serialize sortable MochiKit-1.4.2/examples/dnd_sortable/sortable3_test.html0000660000175000017500000000345411113647642022411 0ustar scottscott script.aculo.us sortable functional test file

script.aculo.us Sortable two-lists w/ dropOnEmpty functional test file

Serialize sortable1 Serialize sortable2
MochiKit-1.4.2/examples/dnd_sortable/sortable2_test.html0000660000175000017500000001362111113647642022405 0ustar scottscott script.aculo.us Sortable ghosting functional test file

script.aculo.us Sortable ghosting functional test file

Ghosting

(waiting for onChange)

No ghosting

(waiting for onChange)

Ghosting (inside position:relative container)

  • Lorem ipsum dolor
  • sit amet
  • consectetur adipisicing
  • elit
  • sed do eiusmod
  • tempor incididunt
  • ut labore et dolore
  • magna aliqua

(waiting for onChange)

Ghosting (inside position:relative container)

  • Lorem ipsum dolor
  • sit amet
  • consectetur adipisicing
  • elit
  • sed do eiusmod
  • tempor incididunt
  • ut labore et dolore
  • magna aliqua

(waiting for onChange)

MochiKit-1.4.2/examples/dnd_sortable/sortable4_test.html0000660000175000017500000000602711113647642022411 0ustar scottscott script.aculo.us sortable functional test file

script.aculo.us: Two floating sortables with containment and dropOnEmpty

This is the first list

  • Item 1 from first list.
  • Item 2 from first list.
  • Item 3 from first list.

And now the second list

  • DRAG HERE Item 1 from second list.
  • DRAG HERE Item 2 from second list.
  • DRAG HERE Item 3 from second list.




 
 
 
 
MochiKit-1.4.2/examples/dnd_sortable/icon.png0000660000175000017500000000043111102215702020176 0ustar  scottscottPNG


IHDRexgAMAOX2tEXtSoftwareAdobe ImageReadyqe<9PLTEBBΔ΄!!!!ssRRֵcc絵{쭃cfIDATxl@CۏZ!@XUgBއ>K
0'-Igt&p!
f&ϴyL.h/EĨ0ݫIENDB`MochiKit-1.4.2/examples/draggable/0000755000175000017500000000000011136470264016031 5ustar  scottscottMochiKit-1.4.2/examples/draggable/draggable.js0000660000175000017500000000362611102215702020267 0ustar  scottscott/*

    Drag: A Really Simple Drag Handler
    
*/
Drag = {
    _move: null,
    _down: null,
    
    start: function(e) {
        e.stop();
        
        // We need to remember what we're dragging.
        Drag._target = e.target();
        
        /*
            There's no cross-browser way to get offsetX and offsetY, so we
            have to do it ourselves. For performance, we do this once and
            cache it.
        */
        Drag._offset = Drag._diff(
            e.mouse().page,
            getElementPosition(Drag._target));
        
        Drag._move = connect(document, 'onmousemove', Drag._drag);
        Drag._down = connect(document, 'onmouseup', Drag._stop);
    },

    _offset: null,
    _target: null,
    
    _diff: function(lhs, rhs) {
        return new MochiKit.Style.Coordinates(lhs.x - rhs.x, lhs.y - rhs.y);
    },
        
    _drag: function(e) {
        e.stop();
        setElementPosition(
            Drag._target,
            Drag._diff(e.mouse().page, Drag._offset));
    },
    
    _stop: function(e) {
        disconnect(Drag._move);
        disconnect(Drag._down);
    }
};

connect(window, 'onload',   
    function() {
        /*
            Find all DIVs tagged with the draggable class, and connect them to
            the Drag handler.
        */
        var d = getElementsByTagAndClassName('DIV', 'draggable');
        forEach(d,
            function(elem) {
                connect(elem, 'onmousedown', Drag.start);
            });
                        
    });
    
connect(window, 'onload',
    function() {
        var elems = getElementsByTagAndClassName("A", "view-source");
        var page = "draggable/";
        for (var i = 0; i < elems.length; i++) {
            var elem = elems[i];
            var href = elem.href.split(/\//).pop();
            elem.target = "_blank";
            elem.href = "../view-source/view-source.html#" + page + href;
        } 
    });
MochiKit-1.4.2/examples/draggable/index.html0000660000175000017500000000240511113647642020026 0ustar  scottscott


    Signal Example
    
    
    



    

Dragging with MochiKit

This is an example of one might implement a drag handler with MochiKit’s Signal.

For a detailed description of what happens under the hood, check out draggable.js.

View Source: [ index.html | draggable.js | draggable.css ]

R
G
B
W
MochiKit-1.4.2/examples/draggable/draggable.css0000660000175000017500000000066311102215702020441 0ustar scottscotth1 { font-size: 2em; color: #4B4545; text-align: center; } .draggable { color: white; cursor: move; font-size: 25px; height: 100px; line-height: 100px; position: absolute; text-align: center; top: 200px; width: 100px; } .blue { background: blue; } .green { background: green; } .red { background: red; } .white { background: white; border: 1px solid black; color: black; } MochiKit-1.4.2/tests/0000755000175000017500000000000011136470265013446 5ustar scottscottMochiKit-1.4.2/tests/test_MochiKit-Selector.html0000660000175000017500000003023611113647642020662 0ustar scottscott

Test originally from this blog entry.

Here are some links in a normal paragraph: Google, Google Groups. This link has class="blog": diveintomark

Everything inside the red border is inside a div with id="foo".

This is a normal link: Yahoo

This a is not inside a p

This link has class="blog": Simon Willison's Weblog

This link is inside a span, not directly child of p

Nonninn

Sniðugt


MochiKit-1.4.2/tests/test_Iter.js0000660000175000017500000001655711102215552015747 0ustar scottscottif (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Iter'); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Iter'); } if (typeof(tests) == 'undefined') { tests = {}; } tests.test_Iter = function (t) { t.is( sum([1, 2, 3, 4, 5]), 15, "sum works on Arrays" ); t.is( compare(list([1, 2, 3]), [1, 2, 3]), 0, "list([x]) == [x]" ); t.is( compare(list(range(6, 0, -1)), [6, 5, 4, 3, 2, 1]), 0, "list(range(6, 0, -1)"); t.is( compare(list(range(6)), [0, 1, 2, 3, 4, 5]), 0, "list(range(6))" ); var moreThanTwo = partial(operator.lt, 2); t.is( sum(ifilter(moreThanTwo, range(6))), 12, "sum(ifilter(, range()))" ); t.is( sum(ifilterfalse(moreThanTwo, range(6))), 3, "sum(ifilterfalse(, range()))" ); var c = count(10); t.is( compare([c.next(), c.next(), c.next()], [10, 11, 12]), 0, "count()" ); c = cycle([1, 2]); t.is( compare([c.next(), c.next(), c.next()], [1, 2, 1]), 0, "cycle()" ); c = repeat("foo", 3); t.is( compare(list(c), ["foo", "foo", "foo"]), 0, "repeat()" ); c = izip([1, 2], [3, 4, 5], repeat("foo")); t.is( compare(list(c), [[1, 3, "foo"], [2, 4, "foo"]]), 0, "izip()" ); t.is( compare(list(range(5)), [0, 1, 2, 3, 4]), 0, "range(x)" ); c = islice(range(10), 0, 10, 2); t.is( compare(list(c), [0, 2, 4, 6, 8]), 0, "islice(x, y, z)" ); c = imap(operator.add, [1, 2, 3], [2, 4, 6]); t.is( compare(list(c), [3, 6, 9]), 0, "imap(fn, p, q)" ); c = filter(partial(operator.lt, 1), iter([1, 2, 3])); t.is( compare(c, [2, 3]), 0, "filter(fn, iterable)" ); c = map(partial(operator.add, -1), iter([1, 2, 3])); t.is( compare(c, [0, 1, 2]), 0, "map(fn, iterable)" ); c = map(operator.add, iter([1, 2, 3]), [2, 4, 6]); t.is( compare(c, [3, 6, 9]), 0, "map(fn, iterable, q)" ); c = map(operator.add, iter([1, 2, 3]), iter([2, 4, 6])); t.is( compare(c, [3, 6, 9]), 0, "map(fn, iterable, iterable)" ); c = applymap(operator.add, [[1, 2], [2, 4], [3, 6]]); t.is( compare(list(c), [3, 6, 9]), 0, "applymap()" ); c = applymap(function (a) { return [this, a]; }, [[1], [2]], 1); t.is( compare(list(c), [[1, 1], [1, 2]]), 0, "applymap(self)" ); c = chain(range(2), range(3)); t.is( compare(list(c), [0, 1, 0, 1, 2]), 0, "chain(p, q)" ); var lessThanFive = partial(operator.gt, 5); c = takewhile(lessThanFive, count()); t.is( compare(list(c), [0, 1, 2, 3, 4]), 0, "takewhile()" ); c = dropwhile(lessThanFive, range(10)); t.is( compare(list(c), [5, 6, 7, 8, 9]), 0, "dropwhile()" ); c = tee(range(5), 3); t.is( compare(list(c[0]), list(c[1])), 0, "tee(..., 3) p0 == p1" ); t.is( compare(list(c[2]), [0, 1, 2, 3, 4]), 0, "tee(..., 3) p2 == fixed" ); t.is( compare(reduce(operator.add, range(10)), 45), 0, "reduce(op.add)" ); try { reduce(operator.add, []); t.ok( false, "reduce didn't raise anything with empty list and no start?!" ); } catch (e) { if (e instanceof TypeError) { t.ok( true, "reduce raised TypeError correctly" ); } else { t.ok( false, "reduce raised the wrong exception?" ); } } t.is( reduce(operator.add, [], 10), 10, "range initial value OK empty" ); t.is( reduce(operator.add, [1], 10), 11, "range initial value OK populated" ); t.is( compare(iextend([1], range(2)), [1, 0, 1]), 0, "iextend(...)" ); var rval = []; var o = [0, 1, 2, 3]; o.next = range(2).next; t.is( iextend([], o).length, 2, "iextend handles array-like iterables" ); var x = []; exhaust(imap(bind(x.push, x), range(5))); t.is( compare(x, [0, 1, 2, 3, 4]), 0, "exhaust(...)" ); t.is( every([1, 2, 3, 4, 5, 4], lessThanFive), false, "every false" ); t.is( every([1, 2, 3, 4, 4], lessThanFive), true, "every true" ); t.is( some([1, 2, 3, 4, 4], lessThanFive), true, "some true" ); t.is( some([5, 6, 7, 8, 9], lessThanFive), false, "some false" ); t.is( some([5, 6, 7, 8, 4], lessThanFive), true, "some true" ); var rval = []; forEach(range(2), rval.push, rval); t.is( compare(rval, [0, 1]), 0, "forEach works bound" ); function foo(o) { rval.push(o); } forEach(range(2), foo); t.is( compare(rval, [0, 1, 0, 1]), 0, "forEach works unbound" ); var rval = []; var o = [0, 1, 2, 3]; o.next = range(2).next; forEach(o, rval.push, rval); t.is( rval.length, 2, "forEach handles array-like iterables" ); t.is( compare(sorted([3, 2, 1]), [1, 2, 3]), 0, "sorted default" ); rval = sorted(["aaa", "bb", "c"], keyComparator("length")); t.is(compare(rval, ["c", "bb", "aaa"]), 0, "sorted custom"); t.is( compare(reversed(range(4)), [3, 2, 1, 0]), 0, "reversed iterator" ); t.is( compare(reversed([5, 6, 7]), [7, 6, 5]), 0, "reversed list" ); var o = {lst: [1, 2, 3], iterateNext: function () { return this.lst.shift(); }}; t.is( compare(list(o), [1, 2, 3]), 0, "iterateNext" ); function except(exc, func) { try { func(); t.ok(false, exc.name + " was not raised."); } catch (e) { if (e == exc) { t.ok( true, "raised " + exc.name + " correctly" ); } else { t.ok( false, "raised the wrong exception?" ); } } } odd = partial(operator.and, 1) // empty grouped = groupby([]); except(StopIteration, grouped.next); // exhaust sub-iterator grouped = groupby([2,4,6,7], odd); kv = grouped.next(); k = kv[0], subiter = kv[1]; t.is(k, 0, "odd(2) = odd(4) = odd(6) == 0"); t.is(subiter.next(), 2, "sub-iterator.next() == 2"); t.is(subiter.next(), 4, "sub-iterator.next() == 4"); t.is(subiter.next(), 6, "sub-iterator.next() == 6"); except(StopIteration, subiter.next); kv = grouped.next(); key = kv[0], subiter = kv[1]; t.is(key, 1, "odd(7) == 1"); t.is(subiter.next(), 7, "sub-iterator.next() == 7"); except(StopIteration, subiter.next); // not consume sub-iterator grouped = groupby([2,4,6,7], odd); kv = grouped.next(); key = kv[0], subiter = kv[1]; t.is(key, 0, "0 = odd(2) = odd(4) = odd(6)"); kv = grouped.next(); key = kv[0], subiter = kv[1]; t.is(key, 1, "1 = odd(7)"); except(StopIteration, grouped.next); // consume sub-iterator partially grouped = groupby([3,1,1,2], odd); kv = grouped.next(); key = kv[0], subiter = kv[1]; t.is(key, 1, "odd(1) == 1"); t.is(subiter.next(), 3, "sub-iterator.next() == 3"); kv = grouped.next(); key = kv[0], v = kv[1]; t.is(key, 0, "skip (1,1), odd(2) == 0"); except(StopIteration, grouped.next); // null grouped = groupby([null,null]); kv = grouped.next(); k = kv[0], v = kv[1]; t.is(k, null, "null ok"); // groupby - array version isEqual = (t.isDeeply || function (a, b, msg) { return t.ok(compare(a, b) == 0, msg); }); isEqual(groupby_as_array([ ] ), [ ], "empty"); isEqual(groupby_as_array([1,1,1]), [ [1,[1,1,1]] ], "[1,1,1]: [1,1,1]"); isEqual(groupby_as_array([1,2,2]), [ [1,[1] ], [2,[2,2]] ], "[1,2,2]: [1], [2,2]"); isEqual(groupby_as_array([1,1,2]), [ [1,[1,1] ], [2,[2 ]] ], "[1,1,2]: [1,1], [2]"); isEqual(groupby_as_array([null,null] ), [ [null,[null,null]] ], "[null,null]: [null,null]"); grouped = groupby_as_array([1,1,3,2,4,6,8], odd); isEqual(grouped, [[1, [1,1,3]], [0,[2,4,6,8]]], "[1,1,3,2,4,6,7] odd: [1,1,3], [2,4,6,8]"); }; MochiKit-1.4.2/tests/test_MochiKit-Color.html0000660000175000017500000000444711113647642020165 0ustar scottscott


MochiKit-1.4.2/tests/test_MochiKit-Iter.html0000660000175000017500000000175711113647642020013 0ustar scottscott


MochiKit-1.4.2/tests/test_Signal.js0000660000175000017500000004356711102215552016262 0ustar scottscottif (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); } if (typeof(tests) == 'undefined') { tests = {}; } tests.test_Signal = function (t) { var submit = MochiKit.DOM.getElement('submit'); var ident = null; var i = 0; var aFunction = function() { t.ok(this === submit, "aFunction should have 'this' as submit"); i++; if (typeof(this.someVar) != 'undefined') { i += this.someVar; } }; var aObject = {}; aObject.aMethod = function() { t.ok(this === aObject, "aMethod should have 'this' as aObject"); i++; }; ident = connect('submit', 'onclick', aFunction); MochiKit.DOM.getElement('submit').click(); t.is(i, 1, 'HTML onclick event can be connected to a function'); disconnect(ident); MochiKit.DOM.getElement('submit').click(); t.is(i, 1, 'HTML onclick can be disconnected from a function'); var submit = MochiKit.DOM.getElement('submit'); ident = connect(submit, 'onclick', aFunction); submit.click(); t.is(i, 2, 'Checking that a DOM element can be connected to a function'); disconnect(ident); submit.click(); t.is(i, 2, '...and then disconnected'); if (MochiKit.DOM.getElement('submit').fireEvent || (document.createEvent && typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) { /* Adapted from: http://www.devdaily.com/java/jwarehouse/jforum/tests/selenium/javascript/htmlutils.js.shtml License: Apache Copyright: Copyright 2004 ThoughtWorks, Inc */ var triggerMouseEvent = function(element, eventType, canBubble) { element = MochiKit.DOM.getElement(element); canBubble = (typeof(canBubble) == 'undefined') ? true : canBubble; if (element.fireEvent) { var newEvt = document.createEventObject(); newEvt.clientX = 1; newEvt.clientY = 1; newEvt.button = 1; newEvt.detail = 3; element.fireEvent('on' + eventType, newEvt); } else if (document.createEvent && (typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) { var evt = document.createEvent('MouseEvents'); evt.initMouseEvent(eventType, canBubble, true, // event, bubbles, cancelable document.defaultView, 3, // view, detail (either scroll or # of clicks) 1, 0, 0, 0, // screenX, screenY, clientX, clientY false, false, false, false, // ctrlKey, altKey, shiftKey, metaKey 0, null); // buttonCode, relatedTarget element.dispatchEvent(evt); } }; var eventTest = function(e) { i++; t.ok((typeof(e.event()) === 'object'), 'checking that event() is an object'); t.ok((typeof(e.type()) === 'string'), 'checking that type() is a string'); t.ok((e.target() === MochiKit.DOM.getElement('submit')), 'checking that target is "submit"'); t.ok((typeof(e.modifier()) === 'object'), 'checking that modifier() is an object'); t.ok(e.modifier().alt === false, 'checking that modifier().alt is defined, but false'); t.ok(e.modifier().ctrl === false, 'checking that modifier().ctrl is defined, but false'); t.ok(e.modifier().meta === false, 'checking that modifier().meta is defined, but false'); t.ok(e.modifier().shift === false, 'checking that modifier().shift is defined, but false'); t.ok((typeof(e.mouse()) === 'object'), 'checking that mouse() is an object'); t.ok((typeof(e.mouse().button) === 'object'), 'checking that mouse().button is an object'); t.ok(e.mouse().button.left === true, 'checking that mouse().button.left is true'); t.ok(e.mouse().button.middle === false, 'checking that mouse().button.middle is false'); t.ok(e.mouse().button.right === false, 'checking that mouse().button.right is false'); t.ok((typeof(e.mouse().page) === 'object'), 'checking that mouse().page is an object'); t.ok((typeof(e.mouse().page.x) === 'number'), 'checking that mouse().page.x is a number'); t.ok((typeof(e.mouse().page.y) === 'number'), 'checking that mouse().page.y is a number'); t.ok((typeof(e.mouse().client) === 'object'), 'checking that mouse().client is an object'); t.ok((typeof(e.mouse().client.x) === 'number'), 'checking that mouse().client.x is a number'); t.ok((typeof(e.mouse().client.y) === 'number'), 'checking that mouse().client.y is a number'); /* these should not be defined */ t.ok((typeof(e.relatedTarget()) === 'undefined'), 'checking that relatedTarget() is undefined'); t.ok((typeof(e.key()) === 'undefined'), 'checking that key() is undefined'); t.ok((typeof(e.mouse().wheel) === 'undefined'), 'checking that mouse().wheel is undefined'); }; ident = connect('submit', 'onmousedown', eventTest); triggerMouseEvent('submit', 'mousedown', false); t.is(i, 3, 'Connecting an event to an HTML object and firing a synthetic event'); disconnect(ident); triggerMouseEvent('submit', 'mousedown', false); t.is(i, 3, 'Disconnecting an event to an HTML object and firing a synthetic event'); ident = connect('submit', 'onmousewheel', function(e) { i++; t.ok((typeof(e.mouse()) === 'object'), 'checking that mouse() is an object'); t.ok((typeof(e.mouse().wheel) === 'object'), 'checking that mouse().wheel is an object'); t.ok((typeof(e.mouse().wheel.x) === 'number'), 'checking that mouse().wheel.x is a number'); t.ok((typeof(e.mouse().wheel.y) === 'number'), 'checking that mouse().wheel.y is a number'); }); var nativeSignal = 'mousewheel'; if (MochiKit.Signal._browserLacksMouseWheelEvent()) { nativeSignal = 'DOMMouseScroll'; } triggerMouseEvent('submit', nativeSignal, false); t.is(i, 4, 'Connecting a mousewheel event to an HTML object and firing a synthetic event'); disconnect(ident); triggerMouseEvent('submit', nativeSignal, false); t.is(i, 4, 'Disconnecting a mousewheel event to an HTML object and firing a synthetic event'); } // non-DOM tests var hasNoSignals = {}; var hasSignals = {someVar: 1}; var i = 0; var aFunction = function() { i++; if (typeof(this.someVar) != 'undefined') { i += this.someVar; } }; var bFunction = function(someArg, someOtherArg) { i += someArg + someOtherArg; }; var aObject = {}; aObject.aMethod = function() { i++; }; aObject.bMethod = function() { i++; }; var bObject = {}; bObject.bMethod = function() { i++; }; ident = connect(hasSignals, 'signalOne', aFunction); signal(hasSignals, 'signalOne'); t.is(i, 2, 'Connecting function'); i = 0; disconnect(ident); signal(hasSignals, 'signalOne'); t.is(i, 0, 'New style disconnecting function'); i = 0; ident = connect(hasSignals, 'signalOne', bFunction); signal(hasSignals, 'signalOne', 1, 2); t.is(i, 3, 'Connecting function'); i = 0; disconnect(ident); signal(hasSignals, 'signalOne', 1, 2); t.is(i, 0, 'New style disconnecting function'); i = 0; connect(hasSignals, 'signalOne', aFunction); signal(hasSignals, 'signalOne'); t.is(i, 2, 'Connecting function'); i = 0; disconnect(hasSignals, 'signalOne', aFunction); signal(hasSignals, 'signalOne'); t.is(i, 0, 'Old style disconnecting function'); i = 0; ident = connect(hasSignals, 'signalOne', aObject, aObject.aMethod); signal(hasSignals, 'signalOne'); t.is(i, 1, 'Connecting obj-function'); i = 0; disconnect(ident); signal(hasSignals, 'signalOne'); t.is(i, 0, 'New style disconnecting obj-function'); i = 0; connect(hasSignals, 'signalOne', aObject, aObject.aMethod); signal(hasSignals, 'signalOne'); t.is(i, 1, 'Connecting obj-function'); i = 0; disconnect(hasSignals, 'signalOne', aObject, aObject.aMethod); signal(hasSignals, 'signalOne'); t.is(i, 0, 'Disconnecting obj-function'); i = 0; ident = connect(hasSignals, 'signalTwo', aObject, 'aMethod'); signal(hasSignals, 'signalTwo'); t.is(i, 1, 'Connecting obj-string'); i = 0; disconnect(ident); signal(hasSignals, 'signalTwo'); t.is(i, 0, 'New style disconnecting obj-string'); i = 0; connect(hasSignals, 'signalTwo', aObject, 'aMethod'); signal(hasSignals, 'signalTwo'); t.is(i, 1, 'Connecting obj-string'); i = 0; disconnect(hasSignals, 'signalTwo', aObject, 'aMethod'); signal(hasSignals, 'signalTwo'); t.is(i, 0, 'Old style disconnecting obj-string'); i = 0; var shouldRaise = function() { return undefined.attr; }; try { connect(hasSignals, 'signalOne', shouldRaise); signal(hasSignals, 'signalOne'); t.ok(false, 'An exception was not raised'); } catch (e) { t.ok(true, 'An exception was raised'); } disconnect(hasSignals, 'signalOne', shouldRaise); t.is(i, 0, 'Exception raised, signal should not have fired'); i = 0; connect(hasSignals, 'signalOne', aObject, 'aMethod'); connect(hasSignals, 'signalOne', aObject, 'bMethod'); signal(hasSignals, 'signalOne'); t.is(i, 2, 'Connecting one signal to two slots in one object'); i = 0; disconnect(hasSignals, 'signalOne', aObject, 'aMethod'); disconnect(hasSignals, 'signalOne', aObject, 'bMethod'); signal(hasSignals, 'signalOne'); t.is(i, 0, 'Disconnecting one signal from two slots in one object'); i = 0; connect(hasSignals, 'signalOne', aObject, 'aMethod'); connect(hasSignals, 'signalOne', bObject, 'bMethod'); signal(hasSignals, 'signalOne'); t.is(i, 2, 'Connecting one signal to two slots in two objects'); i = 0; disconnect(hasSignals, 'signalOne', aObject, 'aMethod'); disconnect(hasSignals, 'signalOne', bObject, 'bMethod'); signal(hasSignals, 'signalOne'); t.is(i, 0, 'Disconnecting one signal from two slots in two objects'); i = 0; try { connect(nothing, 'signalOne', aObject, 'aMethod'); signal(nothing, 'signalOne'); t.ok(false, 'An exception was not raised when connecting undefined'); } catch (e) { t.ok(true, 'An exception was raised when connecting undefined'); } try { disconnect(nothing, 'signalOne', aObject, 'aMethod'); t.ok(false, 'An exception was not raised when disconnecting undefined'); } catch (e) { t.ok(true, 'An exception was raised when disconnecting undefined'); } try { connect(hasSignals, 'signalOne', nothing); signal(hasSignals, 'signalOne'); t.ok(false, 'An exception was not raised when connecting an undefined function'); } catch (e) { t.ok(true, 'An exception was raised when connecting an undefined function'); } try { disconnect(hasSignals, 'signalOne', nothing); t.ok(false, 'An exception was not raised when disconnecting an undefined function'); } catch (e) { t.ok(true, 'An exception was raised when disconnecting an undefined function'); } try { connect(hasSignals, 'signalOne', aObject, aObject.nothing); signal(hasSignals, 'signalOne'); t.ok(false, 'An exception was not raised when connecting an undefined method'); } catch (e) { t.ok(true, 'An exception was raised when connecting an undefined method'); } try { connect(hasSignals, 'signalOne', aObject, 'nothing'); signal(hasSignals, 'signalOne'); t.ok(false, 'An exception was not raised when connecting an undefined method (as string)'); } catch (e) { t.ok(true, 'An exception was raised when connecting an undefined method (as string)'); } t.is(i, 0, 'Signals should not have fired'); connect(hasSignals, 'signalOne', aFunction); connect(hasSignals, 'signalOne', aObject, 'aMethod'); disconnectAll(hasSignals, 'signalOne'); signal(hasSignals, 'signalOne'); t.is(i, 0, 'disconnectAll works with single explicit signal'); i = 0; connect(hasSignals, 'signalOne', aFunction); connect(hasSignals, 'signalOne', aObject, 'aMethod'); connect(hasSignals, 'signalTwo', aFunction); connect(hasSignals, 'signalTwo', aObject, 'aMethod'); disconnectAll(hasSignals, 'signalOne'); signal(hasSignals, 'signalOne'); t.is(i, 0, 'disconnectAll works with single explicit signal'); signal(hasSignals, 'signalTwo'); t.is(i, 3, 'disconnectAll does not disconnect unrelated signals'); i = 0; connect(hasSignals, 'signalOne', aFunction); connect(hasSignals, 'signalOne', aObject, 'aMethod'); connect(hasSignals, 'signalTwo', aFunction); connect(hasSignals, 'signalTwo', aObject, 'aMethod'); disconnectAll(hasSignals, 'signalOne', 'signalTwo'); signal(hasSignals, 'signalOne'); signal(hasSignals, 'signalTwo'); t.is(i, 0, 'disconnectAll works with two explicit signals'); i = 0; connect(hasSignals, 'signalOne', aFunction); connect(hasSignals, 'signalOne', aObject, 'aMethod'); connect(hasSignals, 'signalTwo', aFunction); connect(hasSignals, 'signalTwo', aObject, 'aMethod'); disconnectAll(hasSignals, ['signalOne', 'signalTwo']); signal(hasSignals, 'signalOne'); signal(hasSignals, 'signalTwo'); t.is(i, 0, 'disconnectAll works with two explicit signals as a list'); i = 0; connect(hasSignals, 'signalOne', aFunction); connect(hasSignals, 'signalOne', aObject, 'aMethod'); connect(hasSignals, 'signalTwo', aFunction); connect(hasSignals, 'signalTwo', aObject, 'aMethod'); disconnectAll(hasSignals); signal(hasSignals, 'signalOne'); signal(hasSignals, 'signalTwo'); t.is(i, 0, 'disconnectAll works with implicit signals'); i = 0; var toggle = function() { disconnectAll(hasSignals, 'signalOne'); connect(hasSignals, 'signalOne', aFunction); i++; }; connect(hasSignals, 'signalOne', aFunction); connect(hasSignals, 'signalTwo', function() { i++; }); connect(hasSignals, 'signalTwo', toggle); connect(hasSignals, 'signalTwo', function() { i++; }); // #147 connect(hasSignals, 'signalTwo', function() { i++; }); signal(hasSignals, 'signalTwo'); t.is(i, 4, 'disconnectAll fired in a signal loop works'); i = 0; disconnectAll('signalOne'); disconnectAll('signalTwo'); var testfunc = function () { arguments.callee.count++; }; testfunc.count = 0; var testObj = { methOne: function () { this.countOne++; }, countOne: 0, methTwo: function () { this.countTwo++; }, countTwo: 0 }; connect(hasSignals, 'signalOne', testfunc); connect(hasSignals, 'signalTwo', testfunc); signal(hasSignals, 'signalOne'); signal(hasSignals, 'signalTwo'); t.is(testfunc.count, 2, 'disconnectAllTo func precondition'); disconnectAllTo(testfunc); signal(hasSignals, 'signalOne'); signal(hasSignals, 'signalTwo'); t.is(testfunc.count, 2, 'disconnectAllTo func'); connect(hasSignals, 'signalOne', testObj, 'methOne'); connect(hasSignals, 'signalTwo', testObj, 'methTwo'); signal(hasSignals, 'signalOne'); signal(hasSignals, 'signalTwo'); t.is(testObj.countOne, 1, 'disconnectAllTo obj precondition'); t.is(testObj.countTwo, 1, 'disconnectAllTo obj precondition'); disconnectAllTo(testObj); signal(hasSignals, 'signalOne'); signal(hasSignals, 'signalTwo'); t.is(testObj.countOne, 1, 'disconnectAllTo obj'); t.is(testObj.countTwo, 1, 'disconnectAllTo obj'); testObj.countOne = testObj.countTwo = 0; connect(hasSignals, 'signalOne', testObj, 'methOne'); connect(hasSignals, 'signalTwo', testObj, 'methTwo'); disconnectAllTo(testObj, 'methOne'); signal(hasSignals, 'signalOne'); signal(hasSignals, 'signalTwo'); t.is(testObj.countOne, 0, 'disconnectAllTo obj+str'); t.is(testObj.countTwo, 1, 'disconnectAllTo obj+str'); has__Connect = { count: 0, __connect__: function (ident) { this.count += arguments.length; disconnect(ident); } }; connect(has__Connect, 'signalOne', function() { t.fail("__connect__ should have disconnected signal"); }); t.is(has__Connect.count, 3, '__connect__ is called when it exists'); signal(has__Connect, 'signalOne'); has__Disconnect = { count: 0, __disconnect__: function (ident) { this.count += arguments.length; } }; connect(has__Disconnect, 'signalOne', aFunction); connect(has__Disconnect, 'signalTwo', aFunction); disconnectAll(has__Disconnect); t.is(has__Disconnect.count, 8, '__disconnect__ is called when it exists'); var events = {}; var test_ident = connect(events, "test", function() { var fail_ident = connect(events, "fail", function () { events.failed = true; }); disconnect(fail_ident); signal(events, "fail"); }); signal(events, "test"); t.is(events.failed, undefined, 'disconnected slots do not fire'); var sink = {f: function (ev) { this.ev = ev; }}; var src = {}; bindMethods(sink); connect(src, 'signal', sink.f); signal(src, 'signal', 'worked'); t.is(sink.ev, 'worked', 'custom signal does not re-bind methods'); var lateObj = { fun: function() { this.value = 1; } }; connect(src, 'signal', lateObj, "fun"); signal(src, 'signal'); lateObj.fun = function() { this.value = 2; }; signal(src, 'signal'); t.is(lateObj.value, 2, 'connect uses late function binding'); }; MochiKit-1.4.2/tests/test_Color.js0000660000175000017500000001462511102215552016114 0ustar scottscottif (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Color'); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Color'); } if (typeof(tests) == 'undefined') { tests = {}; } tests.test_Color = function (t) { var approx = function (a, b, msg) { return t.is(a.toPrecision(4), b.toPrecision(4), msg); }; t.is( Color.whiteColor().toHexString(), "#ffffff", "whiteColor has right hex" ); t.is( Color.blackColor().toHexString(), "#000000", "blackColor has right hex" ); t.is( Color.blueColor().toHexString(), "#0000ff", "blueColor has right hex" ); t.is( Color.redColor().toHexString(), "#ff0000", "redColor has right hex" ); t.is( Color.greenColor().toHexString(), "#00ff00", "greenColor has right hex" ); t.is( compare(Color.whiteColor(), Color.whiteColor()), 0, "default colors compare right" ); t.ok( Color.whiteColor() == Color.whiteColor(), "default colors are interned" ); t.ok( Color.whiteColor().toRGBString(), "rgb(255,255,255)", "toRGBString white" ); t.ok( Color.blueColor().toRGBString(), "rgb(0,0,255)", "toRGBString blue" ); t.is( Color.fromRGB(190/255, 222/255, 173/255).toHexString(), "#bedead", "fromRGB works" ); t.is( Color.fromRGB(226/255, 15.9/255, 182/255).toHexString(), "#e210b6", "fromRGB < 16 works" ); t.is( Color.fromRGB({r:190/255,g:222/255,b:173/255}).toHexString(), "#bedead", "alt fromRGB works" ); t.is( Color.fromHexString("#bedead").toHexString(), "#bedead", "round-trip hex" ); t.is( Color.fromString("#bedead").toHexString(), "#bedead", "round-trip string(hex)" ); t.is( Color.fromRGBString("rgb(190,222,173)").toHexString(), "#bedead", "round-trip rgb" ); t.is( Color.fromString("rgb(190,222,173)").toHexString(), "#bedead", "round-trip rgb" ); var hsl = Color.redColor().asHSL(); approx( hsl.h, 0.0, "red hsl.h" ); approx( hsl.s, 1.0, "red hsl.s" ); approx( hsl.l, 0.5, "red hsl.l" ); hsl = Color.fromRGB(0, 0, 0.5).asHSL(); approx( hsl.h, 2/3, "darkblue hsl.h" ); approx( hsl.s, 1.0, "darkblue hsl.s" ); approx( hsl.l, 0.25, "darkblue hsl.l" ); hsl = Color.fromString("#4169E1").asHSL(); approx( hsl.h, (5/8), "4169e1 h"); approx( hsl.s, (8/11), "4169e1 s"); approx( hsl.l, (29/51), "4169e1 l"); hsl = Color.fromString("#555544").asHSL(); approx( hsl.h, (1/6), "555544 h" ); approx( hsl.s, (1/9), "555544 s" ); approx( hsl.l, (3/10), "555544 l" ); hsl = Color.fromRGB(0.5, 1, 0.5).asHSL(); approx( hsl.h, 1/3, "aqua hsl.h" ); approx( hsl.s, 1.0, "aqua hsl.s" ); approx( hsl.l, 0.75, "aqua hsl.l" ); t.is( Color.fromHSL(hsl.h, hsl.s, hsl.l).toHexString(), Color.fromRGB(0.5, 1, 0.5).toHexString(), "fromHSL works with components" ); t.is( Color.fromHSL(hsl).toHexString(), Color.fromRGB(0.5, 1, 0.5).toHexString(), "fromHSL alt form" ); t.is( Color.fromString("hsl(120,100%,75%)").toHexString(), "#80ff80", "fromHSLString" ); t.is( Color.fromRGB(0.5, 1, 0.5).toHSLString(), "hsl(120,100.0%,75.00%)", "toHSLString" ); t.is( Color.fromHSL(0, 0, 0).toHexString(), "#000000", "fromHSL to black" ); hsl = Color.blackColor().asHSL(); approx( hsl.h, 0.0, "black hsl.h" ); approx( hsl.s, 0.0, "black hsl.s" ); approx( hsl.l, 0.0, "black hsl.l" ); hsl.h = 1.0; hsl = Color.blackColor().asHSL(); approx( hsl.h, 0.0, "asHSL returns copy" ); var rgb = Color.brownColor().asRGB(); approx( rgb.r, 153/255, "brown rgb.r" ); approx( rgb.g, 102/255, "brown rgb.g" ); approx( rgb.b, 51/255, "brown rgb.b" ); rgb.r = 0; rgb = Color.brownColor().asRGB(); approx( rgb.r, 153/255, "asRGB returns copy" ); t.is( Color.fromName("aqua").toHexString(), "#00ffff", "aqua fromName" ); t.is( Color.fromString("aqua").toHexString(), "#00ffff", "aqua fromString" ); t.is( Color.fromName("transparent"), Color.transparentColor(), "transparent fromName" ); t.is( Color.fromString("transparent"), Color.transparentColor(), "transparent fromString" ); t.is( Color.transparentColor().toRGBString(), "rgba(0,0,0,0)", "transparent toRGBString" ); t.is( Color.fromRGBString("rgba( 0, 255, 255, 50%)").asRGB().a, 0.5, "rgba parsing alpha correctly" ); t.is( Color.fromRGBString("rgba( 0, 255, 255, 50%)").toRGBString(), "rgba(0,255,255,0.5)", "rgba output correctly" ); t.is( Color.fromRGBString("rgba( 0, 255, 255, 1)").toHexString(), "#00ffff", "fromRGBString with spaces and alpha" ); t.is( Color.fromRGBString("rgb( 0, 255, 255)").toHexString(), "#00ffff", "fromRGBString with spaces" ); t.is( Color.fromRGBString("rgb( 0, 100%, 255)").toHexString(), "#00ffff", "fromRGBString with percents" ); var hsv = Color.redColor().asHSV(); approx( hsv.h, 0.0, "red hsv.h" ); approx( hsv.s, 1.0, "red hsv.s" ); approx( hsv.v, 1.0, "red hsv.v" ); t.is( Color.fromHSV(hsv).toHexString(), Color.redColor().toHexString(), "red hexstring" ); hsv = Color.fromRGB(0, 0, 0.5).asHSV(); approx( hsv.h, 2/3, "darkblue hsv.h" ); approx( hsv.s, 1.0, "darkblue hsv.s" ); approx( hsv.v, 0.5, "darkblue hsv.v" ); t.is( Color.fromHSV(hsv).toHexString(), Color.fromRGB(0, 0, 0.5).toHexString(), "darkblue hexstring" ); hsv = Color.fromString("#4169E1").asHSV(); approx( hsv.h, 5/8, "4169e1 h"); approx( hsv.s, 32/45, "4169e1 s"); approx( hsv.v, 15/17, "4169e1 l"); t.is( Color.fromHSV(hsv).toHexString(), "#4169e1", "4169e1 hexstring" ); hsv = Color.fromString("#555544").asHSV(); approx( hsv.h, 1/6, "555544 h" ); approx( hsv.s, 1/5, "555544 s" ); approx( hsv.v, 1/3, "555544 l" ); t.is( Color.fromHSV(hsv).toHexString(), "#555544", "555544 hexstring" ); hsv = Color.fromRGB(0.5, 1, 0.5).asHSV(); approx( hsv.h, 1/3, "aqua hsv.h" ); approx( hsv.s, 0.5, "aqua hsv.s" ); approx( hsv.v, 1, "aqua hsv.v" ); t.is( Color.fromHSV(hsv.h, hsv.s, hsv.v).toHexString(), Color.fromRGB(0.5, 1, 0.5).toHexString(), "fromHSV works with components" ); t.is( Color.fromHSV(hsv).toHexString(), Color.fromRGB(0.5, 1, 0.5).toHexString(), "fromHSV alt form" ); hsv = Color.fromRGB(1, 1, 1).asHSV() approx( hsv.h, 0, 'white hsv.h' ); approx( hsv.s, 0, 'white hsv.s' ); approx( hsv.v, 1, 'white hsv.v' ); t.is( Color.fromHSV(0, 0, 1).toHexString(), '#ffffff', 'HSV saturation' ); }; MochiKit-1.4.2/tests/test_MochiKit-Signal.html0000660000175000017500000000232111113647642020311 0ustar scottscott Please ignore this button:


MochiKit-1.4.2/tests/test_DateTime.js0000660000175000017500000000561411102215552016530 0ustar scottscottif (typeof(dojo) != 'undefined') { dojo.require('MochiKit.DateTime'); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.DateTime'); } if (typeof(tests) == 'undefined') { tests = {}; } tests.test_DateTime = function (t) { var testDate = isoDate('2005-2-3'); t.is(testDate.getFullYear(), 2005, "isoDate year ok"); t.is(testDate.getDate(), 3, "isoDate day ok"); t.is(testDate.getMonth(), 1, "isoDate month ok"); t.ok(objEqual(testDate, new Date("February 3, 2005")), "matches string date"); t.is(toISODate(testDate), '2005-02-03', 'toISODate ok'); var testDate = isoDate('2005-06-08'); t.is(testDate.getFullYear(), 2005, "isoDate year ok"); t.is(testDate.getDate(), 8, "isoDate day ok"); t.is(testDate.getMonth(), 5, "isoDate month ok"); t.ok(objEqual(testDate, new Date("June 8, 2005")), "matches string date"); t.is(toISODate(testDate), '2005-06-08', 'toISODate ok'); var testDate = isoDate('0500-12-12'); t.is(testDate.getFullYear(), 500, 'isoDate year ok for year < 1000'); t.is(testDate.getDate(), 12, 'isoDate day ok for year < 1000'); t.is(testDate.getMonth(), 11, 'isoDate month ok for year < 1000'); t.ok(objEqual(testDate, new Date("December 12, 0500")), "matches string date for year < 1000"); t.is(toISODate(testDate), '0500-12-12', 'toISODate ok for year < 1000'); t.is(compare(new Date("February 3, 2005"), new Date(2005, 1, 3)), 0, "dates compare eq"); t.is(compare(new Date("February 3, 2005"), new Date(2005, 2, 3)), -1, "dates compare lt"); t.is(compare(new Date("February 3, 2005"), new Date(2005, 0, 3)), 1, "dates compare gt"); var testDate = isoDate('2005-2-3'); t.is(compare(americanDate('2/3/2005'), testDate), 0, "americanDate eq"); t.is(compare('2/3/2005', toAmericanDate(testDate)), 0, "toAmericanDate eq"); var testTimestamp = isoTimestamp('2005-2-3 22:01:03'); t.is(compare(testTimestamp, new Date(2005,1,3,22,1,3)), 0, "isoTimestamp eq"); t.is(compare(testTimestamp, isoTimestamp('2005-2-3T22:01:03')), 0, "isoTimestamp (real ISO) eq"); t.is(compare(toISOTimestamp(testTimestamp), '2005-02-03 22:01:03'), 0, "toISOTimestamp eq"); testTimestamp = isoTimestamp('2005-2-3T22:01:03Z'); t.is(toISOTimestamp(testTimestamp, true), '2005-02-03T22:01:03Z', "toISOTimestamp (real ISO) eq"); var localTZ = Math.round((new Date(2005,1,3,22,1,3)).getTimezoneOffset()/60) var direction = (localTZ < 0) ? "+" : "-"; localTZ = Math.abs(localTZ); localTZ = direction + ((localTZ < 10) ? "0" : "") + localTZ; testTimestamp = isoTimestamp("2005-2-3T22:01:03" + localTZ); var testDateTimestamp = new Date(2005,1,3,22,1,3); t.is(compare(testTimestamp, testDateTimestamp), 0, "equal with local tz"); testTimestamp = isoTimestamp("2005-2-3T17:01:03-05"); var testDateTimestamp = new Date(Date.UTC(2005,1,3,22,1,3)); t.is(compare(testTimestamp, testDateTimestamp), 0, "equal with specific tz"); }; MochiKit-1.4.2/tests/test_MochiKit-MochiKit.html0000660000175000017500000000114111113647642020602 0ustar scottscott

MochiKit-1.4.2/tests/test_MochiKit-Style.html0000660000175000017500000002210711113647642020200 0ustar scottscott
TESTSUB
Float
1 2 3

MochiKit-1.4.2/tests/test_MochiKit-Base.html0000660000175000017500000000171211113647642017751 0ustar scottscott


MochiKit-1.4.2/tests/test_MochiKit-Logging.html0000660000175000017500000000210411113647642020461 0ustar scottscott


MochiKit-1.4.2/tests/index.html0000660000175000017500000000126311113647642015443 0ustar scottscott MochiKit-1.4.2/tests/test_MochiKit-DateTime.html0000660000175000017500000000210611113647642020571 0ustar scottscott


MochiKit-1.4.2/tests/test_MochiKit-Async.html0000660000175000017500000002712511113647642020162 0ustar scottscott

MochiKit-1.4.2/tests/test_Base.js0000660000175000017500000005661611102215552015716 0ustar scottscottif (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Base'); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Base'); } if (typeof(tests) == 'undefined') { tests = {}; } tests.test_Base = function (t) { // test bind var not_self = {"toString": function () { return "not self"; } }; var self = {"toString": function () { return "self"; } }; var func = function (arg) { return this.toString() + " " + arg; }; var boundFunc = bind(func, self); not_self.boundFunc = boundFunc; t.is( boundFunc("foo"), "self foo", "boundFunc bound to self properly" ); t.is( not_self.boundFunc("foo"), "self foo", "boundFunc bound to self on another obj" ); t.is( bind(boundFunc, not_self)("foo"), "not self foo", "boundFunc successfully rebound!" ); t.is( bind(boundFunc, undefined, "foo")(), "self foo", "boundFunc partial no self change" ); t.is( bind(boundFunc, not_self, "foo")(), "not self foo", "boundFunc partial self change" ); // test method not_self = {"toString": function () { return "not self"; } }; self = {"toString": function () { return "self"; } }; func = function (arg) { return this.toString() + " " + arg; }; var boundMethod = method(self, func); not_self.boundMethod = boundMethod; t.is( boundMethod("foo"), "self foo", "boundMethod bound to self properly" ); t.is( not_self.boundMethod("foo"), "self foo", "boundMethod bound to self on another obj" ); t.is( method(not_self, boundMethod)("foo"), "not self foo", "boundMethod successfully rebound!" ); t.is( method(undefined, boundMethod, "foo")(), "self foo", "boundMethod partial no self change" ); t.is( method(not_self, boundMethod, "foo")(), "not self foo", "boundMethod partial self change" ); // test bindLate self = {"toString": function () { return "self"; } }; boundFunc = bindLate("toString", self); t.is( boundFunc(), "self", "bindLate binds properly" ); self.toString = function () { return "not self"; }; t.is( boundFunc(), "not self", "bindLate late function lookup" ); func = function (arg) { return this.toString() + " " + arg; }; boundFunc = bindLate(func, self); t.is( boundFunc("foo"), "not self foo", "bindLate fallback to standard bind" ); // test bindMethods var O = function (value) { bindMethods(this); this.value = value; }; O.prototype.func = function () { return this.value; }; var o = new O("boring"); var p = {}; p.func = o.func; var func = o.func; t.is( o.func(), "boring", "bindMethods doesn't break shit" ); t.is( p.func(), "boring", "bindMethods works on other objects" ); t.is( func(), "boring", "bindMethods works on functions" ); var p = clone(o); t.ok( p instanceof O, "cloned correct inheritance" ); var q = clone(p); t.ok( q instanceof O, "clone-cloned correct inheritance" ); q.foo = "bar"; t.is( p.foo, undefined, "clone-clone is copy-on-write" ); p.bar = "foo"; t.is( o.bar, undefined, "clone is copy-on-write" ); t.is( q.bar, "foo", "clone-clone has proper delegation" ); // unbind p.func = bind(p.func, null); t.is( p.func(), "boring", "clone function calls correct" ); q.value = "awesome"; t.is( q.func(), "awesome", "clone really does work" ); // test boring boolean funcs t.is( isNull(null), true, "isNull matches null" ); t.is( isNull(undefined), false, "isNull doesn't match undefined" ); t.is( isNull({}), false, "isNull doesn't match objects" ); t.is( isCallable(isCallable), true, "isCallable returns true on itself" ); t.is( isCallable(1), false, "isCallable returns false on numbers" ); t.is( isUndefined(null), false, "null is not undefined" ); t.is( isUndefined(""), false, "empty string is not undefined" ); t.is( isUndefined(undefined), true, "undefined is undefined" ); t.is( isUndefined({}.foo), true, "missing property is undefined" ); t.is( isUndefinedOrNull(null), true, "null is undefined or null" ); t.is( isUndefinedOrNull(""), false, "empty string is not undefined or null" ); t.is( isUndefinedOrNull(undefined), true, "undefined is undefined or null" ); t.is( isUndefinedOrNull({}.foo), true, "missing property is undefined or null" ); t.is( isEmpty(null), true, "isEmpty null" ); t.is( isEmpty([], [], ""), true, "isEmpty true" ); t.is( isEmpty([], [1], ""), true, "isEmpty true" ); t.is( isEmpty([1], [1], "1"), false, "isEmpty false" ); t.is( isEmpty([1], [1], "1"), false, "isEmpty false" ); t.is( isNotEmpty(null), false, "isNotEmpty null" ); t.is( isNotEmpty([], [], ""), false, "isNotEmpty false" ); t.is( isNotEmpty([], [1], ""), false, "isNotEmpty false" ); t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" ); t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" ); t.is( isArrayLike(undefined), false, "isArrayLike(undefined)" ); t.is( isArrayLike(null), false, "isArrayLike(null)" ); t.is( isArrayLike([]), true, "isArrayLike([])" ); // test extension of arrays var a = []; var b = []; var three = [1, 2, 3]; extend(a, three, 1); t.ok( objEqual(a, [2, 3]), "extend to an empty array" ); extend(a, three, 1) t.ok( objEqual(a, [2, 3, 2, 3]), "extend to a non-empty array" ); extend(b, three); t.ok( objEqual(b, three), "extend of an empty array" ); var c1 = extend(null, three); t.ok( objEqual(c1, three), "extend null" ); var c2 = extend(undefined, three); t.ok( objEqual(c2, three), "extend undefined" ); t.is( compare(1, 2), -1, "numbers compare lt" ); t.is( compare(2, 1), 1, "numbers compare gt" ); t.is( compare(1, 1), 0, "numbers compare eq" ); t.is( compare([1], [1]), 0, "arrays compare eq" ); t.is( compare([1], [1, 2]), -1, "arrays compare lt (length)" ); t.is( compare([1, 2], [2, 1]), -1, "arrays compare lt (contents)" ); t.is( compare([1, 2], [1]), 1, "arrays compare gt (length)" ); t.is( compare([2, 1], [1, 1]), 1, "arrays compare gt (contents)" ); // test partial application var a = []; var func = function (a, b) { if (arguments.length != 2) { return "bad args"; } else { return this.value + a + b; } }; var self = {"value": 1, "func": func}; var self2 = {"value": 2}; t.is( self.func(2, 3), 6, "setup for test is correct" ); self.funcTwo = partial(self.func, 2); t.is( self.funcTwo(3), 6, "partial application works" ); t.is( self.funcTwo(3), 6, "partial application works still" ); t.is( bind(self.funcTwo, self2)(3), 7, "rebinding partial works" ); self.funcTwo = bind(bind(self.funcTwo, self2), null); t.is( self.funcTwo(3), 6, "re-unbinding partial application works" ); // nodeWalk test // ... looks a lot like a DOM tree on purpose var tree = { "id": "nodeWalkTestTree", "test:int": "1", "childNodes": [ { "test:int": "2", "childNodes": [ {"test:int": "5"}, "ignored string", {"ignored": "object"}, ["ignored", "list"], { "test:skipchildren": "1", "childNodes": [{"test:int": 6}] } ] }, {"test:int": "3"}, {"test:int": "4"} ] } var visitedNodes = []; nodeWalk(tree, function (node) { var attr = node["test:int"]; if (attr) { visitedNodes.push(attr); } if (node["test:skipchildren"]) { return; } return node.childNodes; }); t.ok( objEqual(visitedNodes, ["1", "2", "3", "4", "5"]), "nodeWalk looks like it works"); // test map var minusOne = function (x) { return x - 1; }; var res = map(minusOne, [1, 2, 3]); t.ok( objEqual(res, [0, 1, 2]), "map works" ); var res2 = xmap(minusOne, 1, 2, 3); t.ok( objEqual(res2, res), "xmap works" ); res = map(operator.add, [1, 2, 3], [2, 4, 6]); t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works" ); res = map(operator.add, [1, 2, 3], [2, 4, 6, 8]); t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (q long)" ); res = map(operator.add, [1, 2, 3, 4], [2, 4, 6]); t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (p long)" ); res = map(null, [1, 2, 3], [2, 4, 6]); t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "map(null, p, q) works" ); res = zip([1, 2, 3], [2, 4, 6]); t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "zip(p, q) works" ); res = map(null, [1, 2, 3]); t.ok( objEqual(res, [1, 2, 3]), "map(null, lst) works" ); t.is( isNotEmpty("foo"), true, "3 char string is not empty" ); t.is( isNotEmpty(""), false, "0 char string is empty" ); t.is( isNotEmpty([1, 2, 3]), true, "3 element list is not empty" ); t.is( isNotEmpty([]), false, "0 element list is empty" ); // test filter var greaterThanThis = function (x) { return x > this; }; var greaterThanOne = function (x) { return x > 1; }; var res = filter(greaterThanOne, [-1, 0, 1, 2, 3]); t.ok( objEqual(res, [2, 3]), "filter works" ); var res = filter(greaterThanThis, [-1, 0, 1, 2, 3], 1); t.ok( objEqual(res, [2, 3]), "filter self works" ); var res2 = xfilter(greaterThanOne, -1, 0, 1, 2, 3); t.ok( objEqual(res2, res), "xfilter works" ); t.is(objMax(1, 2, 9, 12, 42, -16, 16), 42, "objMax works (with numbers)"); t.is(objMin(1, 2, 9, 12, 42, -16, 16), -16, "objMin works (with numbers)"); // test adapter registry var R = new AdapterRegistry(); R.register("callable", isCallable, function () { return "callable"; }); R.register("arrayLike", isArrayLike, function () { return "arrayLike"; }); t.is( R.match(function () {}), "callable", "registry found callable" ); t.is( R.match([]), "arrayLike", "registry found ArrayLike" ); try { R.match(null); t.ok( false, "non-matching didn't raise!" ); } catch (e) { t.is( e, NotFound, "non-matching raised correctly" ); } R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" }); R.register("undefined", isUndefined, function () { return "undefined" }); t.is( R.match(undefined), "undefinedOrNull", "priorities are as documented" ); t.ok( R.unregister("undefinedOrNull"), "removed adapter" ); t.is( R.match(undefined), "undefined", "adapter was removed" ); R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" }, true); t.is( R.match(undefined), "undefinedOrNull", "override works" ); var a1 = {"a": 1, "b": 2, "c": 2}; var a2 = {"a": 2, "b": 1, "c": 2}; t.is( keyComparator("a")(a1, a2), -1, "keyComparator 1 lt" ); t.is( keyComparator("c")(a1, a2), 0, "keyComparator 1 eq" ); t.is( keyComparator("c", "b")(a1, a2), 1, "keyComparator 2 eq gt" ); t.is( keyComparator("c", "a")(a1, a2), -1, "keyComparator 2 eq lt" ); t.is( reverseKeyComparator("a")(a1, a2), 1, "reverseKeyComparator" ); t.is( compare(concat([1], [2], [3]), [1, 2, 3]), 0, "concat" ); t.is( repr("foo"), '"foo"', "string repr" ); t.is( repr(1), '1', "number repr" ); t.is( listMin([1, 3, 5, 3, -1]), -1, "listMin" ); t.is( objMin(1, 3, 5, 3, -1), -1, "objMin" ); t.is( listMax([1, 3, 5, 3, -1]), 5, "listMax" ); t.is( objMax(1, 3, 5, 3, -1), 5, "objMax" ); var v = keys(a1); v.sort(); t.is( compare(v, ["a", "b", "c"]), 0, "keys" ); v = items(a1); v.sort(); t.is( compare(v, [["a", 1], ["b", 2], ["c", 2]]), 0, "items" ); var StringMap = function() {}; a = new StringMap(); a.foo = "bar"; b = new StringMap(); b.foo = "bar"; try { compare(a, b); t.ok( false, "bad comparison registered!?" ); } catch (e) { t.ok( e instanceof TypeError, "bad comparison raised TypeError" ); } t.is( repr(a), "[object Object]", "default repr for StringMap" ); var isStringMap = function () { for (var i = 0; i < arguments.length; i++) { if (!(arguments[i] instanceof StringMap)) { return false; } } return true; }; registerRepr("stringMap", isStringMap, function (obj) { return "StringMap(" + repr(items(obj)) + ")"; } ); t.is( repr(a), 'StringMap([["foo", "bar"]])', "repr worked" ); // not public API MochiKit.Base.reprRegistry.unregister("stringMap"); t.is( repr(a), "[object Object]", "default repr for StringMap" ); registerComparator("stringMap", isStringMap, function (a, b) { // no sorted(...) in base a = items(a); b = items(b); a.sort(compare); b.sort(compare); return compare(a, b); } ); t.is( compare(a, b), 0, "registerComparator" ); update(a, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1}); t.is( a.foo, "bar", "update worked (first obj)" ); t.is( a.wibble, "baz", "update worked (second obj)" ); t.is( a.grr, 1, "update worked (skipped undefined and null)" ); t.is( compare(a, b), 1, "update worked (comparison)" ); setdefault(a, {"foo": "unf"}, {"bar": "web taco"} ); t.is( a.foo, "bar", "setdefault worked (skipped existing)" ); t.is( a.bar, "web taco", "setdefault worked (set non-existing)" ); a = null; a = setdefault(null, {"foo": "bar"}); t.is( a.foo, "bar", "setdefault worked (self is null)" ); a = null; a = setdefault(undefined, {"foo": "bar"}); t.is( a.foo, "bar", "setdefault worked (self is undefined)" ); a = null; a = update(null, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1}); t.is( a.foo, "bar", "update worked (self is null, first obj)" ); t.is( a.wibble, "baz", "update worked (self is null, second obj)" ); t.is( a.grr, 1, "update worked (self is null, skipped undefined and null)" ); a = null; a = update(undefined, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1}); t.is( a.foo, "bar", "update worked (self is undefined, first obj)" ); t.is( a.wibble, "baz", "update worked (self is undefined, second obj)" ); t.is( a.grr, 1, "update worked (self is undefined, skipped undefined and null)" ); var c = items(merge({"foo": "bar"}, {"wibble": "baz"})); c.sort(compare); t.is( compare(c, [["foo", "bar"], ["wibble", "baz"]]), 0, "merge worked" ); // not public API MochiKit.Base.comparatorRegistry.unregister("stringMap"); try { compare(a, b); t.ok( false, "bad comparison registered!?" ); } catch (e) { t.ok( e instanceof TypeError, "bad comparison raised TypeError" ); } var o = {"__repr__": function () { return "__repr__"; }}; t.is( repr(o), "__repr__", "__repr__ protocol" ); t.is( repr(MochiKit.Base), MochiKit.Base.__repr__(), "__repr__ protocol when repr is defined" ); var o = {"NAME": "NAME"}; t.is( repr(o), "NAME", "NAME protocol (obj)" ); o = function () { return "TACO" }; o.NAME = "NAME"; t.is( repr(o), "NAME", "NAME protocol (func)" ); t.is( repr(MochiKit.Base.nameFunctions), "MochiKit.Base.nameFunctions", "test nameFunctions" ); // Done! t.is( urlEncode("1+2=2").toUpperCase(), "1%2B2%3D2", "urlEncode" ); t.is( queryString(["a", "b"], [1, "two"]), "a=1&b=two", "queryString"); t.is( queryString({"a": 1}), "a=1", "one item alternate form queryString" ); var o = {"a": 1, "b": 2, "c": function() {}}; var res = queryString(o).split("&"); res.sort(); t.is( res.join("&"), "a=1&b=2", "two item alternate form queryString, function skip" ); var res = parseQueryString("1+1=2&b=3%3D2"); t.is( res["1 1"], "2", "parseQueryString pathological name" ); t.is( res.b, "3=2", "parseQueryString second name:value pair" ); var res = parseQueryString("foo=one&foo=two", true); t.is( res["foo"].join(" "), "one two", "parseQueryString useArrays" ); var res = parseQueryString("?foo=2&bar=1"); t.is( res["foo"], "2", "parseQueryString strip leading question mark"); var res = parseQueryString("x=1&y=2"); t.is( typeof(res['&']), "undefined", "extra cruft in parseQueryString output"); t.is( serializeJSON("foo\n\r\b\f\t\u000B\u001B"), "\"foo\\n\\r\\b\\f\\t\\u000B\\u001B\"", "string JSON" ); t.is( serializeJSON(null), "null", "null JSON"); try { serializeJSON(undefined); t.ok(false, "undefined should not be serializable"); } catch (e) { t.ok(e instanceof TypeError, "undefined not serializable"); } t.is( serializeJSON(1), "1", "1 JSON"); t.is( serializeJSON(1.23), "1.23", "1.23 JSON"); t.is( serializeJSON(serializeJSON), null, "function JSON (null, not string)" ); t.is( serializeJSON([1, "2", 3.3]), "[1, \"2\", 3.3]", "array JSON" ); var res = evalJSON(serializeJSON({"a":1, "b":2})); t.is( res.a, 1, "evalJSON on an object (1)" ); t.is( res.b, 2, "evalJSON on an object (2)" ); var res = {"a": 1, "b": 2, "json": function () { return this; }}; var res = evalJSON(serializeJSON(res)); t.is( res.a, 1, "evalJSON on an object that jsons self (1)" ); t.is( res.b, 2, "evalJSON on an object that jsons self (2)" ); var strJSON = {"a": 1, "b": 2, "json": function () { return "json"; }}; t.is( serializeJSON(strJSON), "\"json\"", "json serialization calling" ); t.is( serializeJSON([strJSON]), "[\"json\"]", "json serialization calling in a structure" ); t.is( evalJSON('/* {"result": 1} */').result, 1, "json comment stripping" ); t.is( evalJSON('/* {"*/ /*": 1} */')['*/ /*'], 1, "json comment stripping" ); registerJSON("isDateLike", isDateLike, function (d) { return "this was a date"; } ); t.is( serializeJSON(new Date()), "\"this was a date\"", "json registry" ); MochiKit.Base.jsonRegistry.unregister("isDateLike"); var a = {"foo": {"bar": 12, "wibble": 13}}; var b = {"foo": {"baz": 4, "bar": 16}, "bar": 4}; updatetree(a, b); var expect = [["bar", 16], ["baz", 4], ["wibble", 13]]; var got = items(a.foo); got.sort(compare); t.is( repr(got), repr(expect), "updatetree merge" ); t.is( a.bar, 4, "updatetree insert" ); var aa = {"foo": {"bar": 12, "wibble": 13}}; var bb = {"foo": {"baz": 4, "bar": 16}, "bar": 4}; cc = updatetree(null, aa, bb); got = items(cc.foo); got.sort(compare); t.is( repr(got), repr(expect), "updatetree merge (self is null)" ); t.is( cc.bar, 4, "updatetree insert (self is null)" ); cc = updatetree(undefined, aa, bb); got = items(cc.foo); got.sort(compare); t.is( repr(got), repr(expect), "updatetree merge (self is undefined)" ); t.is( cc.bar, 4, "updatetree insert (self is undefined)" ); var c = counter(); t.is( c(), 1, "counter starts at 1" ); t.is( c(), 2, "counter increases" ); c = counter(2); t.is( c(), 2, "counter starts at 2" ); t.is( c(), 3, "counter increases" ); t.is( findValue([1, 2, 3], 4), -1, "findValue returns -1 on not found"); t.is( findValue([1, 2, 3], 1), 0, "findValue returns correct index"); t.is( findValue([1, 2, 3], 1, 1), -1, "findValue honors start"); t.is( findValue([1, 2, 3], 2, 0, 1), -1, "findValue honors end"); t.is( findIdentical([1, 2, 3], 4), -1, "findIdentical returns -1"); t.is( findIdentical([1, 2, 3], 1), 0, "findIdentical returns correct index"); t.is( findIdentical([1, 2, 3], 1, 1), -1, "findIdentical honors start"); t.is( findIdentical([1, 2, 3], 2, 0, 1), -1, "findIdentical honors end"); var flat = flattenArguments(1, "2", 3, [4, [5, [6, 7], 8, [], 9]]); var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9]; t.is( repr(flat), repr(expect), "flattenArguments" ); var fn = function () { return [this, concat(arguments)]; } t.is( methodcaller("toLowerCase")("FOO"), "foo", "methodcaller with a method name" ); t.is( repr(methodcaller(fn, 2, 3)(1)), "[1, [2, 3]]", "methodcaller with a function" ); var f1 = function (x) { return [1, x]; }; var f2 = function (x) { return [2, x]; }; var f3 = function (x) { return [3, x]; }; t.is( repr(f1(f2(f3(4)))), "[1, [2, [3, 4]]]", "test the compose test" ); t.is( repr(compose(f1,f2,f3)(4)), "[1, [2, [3, 4]]]", "three fn composition works" ); t.is( repr(compose(compose(f1,f2),f3)(4)), "[1, [2, [3, 4]]]", "associative left" ); t.is( repr(compose(f1,compose(f2,f3))(4)), "[1, [2, [3, 4]]]", "associative right" ); try { compose(f1, "foo"); t.ok( false, "wrong compose argument not raised!" ); } catch (e) { t.is( e.name, 'TypeError', "wrong compose argument raised correctly" ); } t.is(camelize('one'), 'one', 'one word'); t.is(camelize('one-two'), 'oneTwo', 'two words'); t.is(camelize('one-two-three'), 'oneTwoThree', 'three words'); t.is(camelize('1-one'), '1One', 'letter and word'); t.is(camelize('one-'), 'one', 'trailing hyphen'); t.is(camelize('-one'), 'One', 'starting hyphen'); t.is(camelize('o-two'), 'oTwo', 'one character and word'); var flat = flattenArray([1, "2", 3, [4, [5, [6, 7], 8, [], 9]]]); var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9]; t.is( repr(flat), repr(expect), "flattenArray" ); /* mean */ try { mean(); t.ok( false, "mean no arguments didn't raise!" ); } catch (e) { t.is( e.name, 'TypeError', "no arguments raised correctly" ); } t.is( mean(1), 1, 'single argument (arg list)'); t.is( mean([1]), 1, 'single argument (array)'); t.is( mean(1,2,3), 2, 'three arguments (arg list)'); t.is( mean([1,2,3]), 2, 'three arguments (array)'); t.is( average(1), 1, 'test the average alias'); /* median */ try { median(); t.ok( false, "median no arguments didn't raise!" ); } catch (e) { t.is( e.name, 'TypeError', "no arguments raised correctly" ); } t.is( median(1), 1, 'single argument (arg list)'); t.is( median([1]), 1, 'single argument (array)'); t.is( median(3,1,2), 2, 'three arguments (arg list)'); t.is( median([3,1,2]), 2, 'three arguments (array)'); t.is( median(3,1,2,4), 2.5, 'four arguments (arg list)'); t.is( median([3,1,2,4]), 2.5, 'four arguments (array)'); /* #185 */ t.is( serializeJSON(parseQueryString("")), "{}", "parseQueryString('')" ); t.is( serializeJSON(parseQueryString("", true)), "{}", "parseQueryString('', true)" ); /* #109 */ t.is( queryString({ids: [1,2,3]}), "ids=1&ids=2&ids=3", "queryString array value" ); t.is( queryString({ids: "123"}), "ids=123", "queryString string value" ); /* test values */ var o = {a: 1, b: 2, c: 4, d: -1}; var got = values(o); got.sort(); t.is( repr(got), repr([-1, 1, 2, 4]), "values()" ); t.is( queryString([["foo", "bar"], ["baz", "wibble"]]), "foo=baz&bar=wibble" ); o = parseQueryString("foo=1=1=1&bar=2&baz&wibble="); t.is( o.foo, "1=1=1", "parseQueryString multiple = first" ); t.is( o.bar, "2", "parseQueryString multiple = second" ); t.is( o.baz, "", "parseQueryString multiple = third" ); t.is( o.wibble, "", "parseQueryString multiple = fourth" ); /* queryString with null values */ t.is( queryString(["a", "b"], [1, null]), "a=1", "queryString with null value" ); t.is( queryString({"a": 1, "b": null}), "a=1", "queryString with null value" ); var reprFunc = function (a, b) { return; } t.is( repr(reprFunc), "function (a, b) {...}", "repr of function" ); }; MochiKit-1.4.2/tests/SimpleTest/0000755000175000017500000000000011136470265015537 5ustar scottscottMochiKit-1.4.2/tests/SimpleTest/test.css0000660000175000017500000000056311102215550017215 0ustar scottscott.test_ok { color: green; display: none; } .test_not_ok { color: red; display: block; } .test_ok, .test_not_ok { border-bottom-width: 2px; border-bottom-style: solid; border-bottom-color: black; } .all_pass { background-color: lime; } .some_fail { background-color: red; } .tests_report { border-width: 2px; border-style: solid; width: 20em; } MochiKit-1.4.2/tests/SimpleTest/SimpleTest.js0000660000175000017500000002641711102215550020161 0ustar scottscott/** * SimpleTest, a partial Test.Simple/Test.More API compatible test library. * * Why? * * Test.Simple doesn't work on IE < 6. * TODO: * * Support the Test.Simple API used by MochiKit, to be able to test MochiKit * itself against IE 5.5 * **/ if (typeof(SimpleTest) == "undefined") { var SimpleTest = {}; } // Check to see if the TestRunner is present and has logging if (typeof(parent) != "undefined" && parent.TestRunner) { SimpleTest._logEnabled = parent.TestRunner.logEnabled; } SimpleTest._tests = []; SimpleTest._stopOnLoad = true; /** * Something like assert. */ SimpleTest.ok = function (condition, name, diag) { var test = {'result': !!condition, 'name': name, 'diag': diag || ""}; if (SimpleTest._logEnabled) { var msg = test.result ? "PASS" : "FAIL"; msg += " | " + test.name; if (test.result) { parent.TestRunner.logger.log(msg); } else { msg += " | " + test.diag; parent.TestRunner.logger.error(msg); } } SimpleTest._tests.push(test); }; /** * Roughly equivalent to ok(a==b, name) */ SimpleTest.is = function (a, b, name) { var repr = MochiKit.Base.repr; SimpleTest.ok(a == b, name, "got " + repr(a) + ", expected " + repr(b)); }; /** * Roughly equivalent to ok(compare(a,b)==0, name) */ SimpleTest.eq = function (a, b, name) { var repr = MochiKit.Base.repr; try { SimpleTest.ok(compare(a, b) == 0, name, "got " + repr(a) + ", expected " + repr(b)); } catch (e) { SimpleTest.ok(false, name, "exception in compare: " + repr(e)); } }; /** * Makes a test report, returns it as a DIV element. **/ SimpleTest.report = function () { var DIV = MochiKit.DOM.DIV; var passed = 0; var failed = 0; var results = MochiKit.Base.map( function (test) { var cls, msg; if (test.result) { passed++; cls = "test_ok"; msg = "ok - " + test.name; } else { failed++; cls = "test_not_ok"; msg = "not ok - " + test.name; if (test.diag != null && test.diag != "") { msg += ": " + test.diag; } } return DIV({"class": cls}, msg); }, SimpleTest._tests ); var summary_class = ((failed == 0) ? 'all_pass' : 'some_fail'); return DIV({'class': 'tests_report'}, DIV({'class': 'tests_summary ' + summary_class}, DIV({'class': 'tests_passed'}, "Passed: " + passed), DIV({'class': 'tests_failed'}, "Failed: " + failed)), results ); }; /** * Toggle element visibility **/ SimpleTest.toggle = function(el) { if (MochiKit.Style.getStyle(el, 'display') == 'block') { el.style.display = 'none'; } else { el.style.display = 'block'; } }; /** * Toggle visibility for divs with a specific class. **/ SimpleTest.toggleByClass = function (cls) { var elems = getElementsByTagAndClassName('div', cls); MochiKit.Base.map(SimpleTest.toggle, elems); }; /** * Shows the report in the browser **/ SimpleTest.showReport = function() { var togglePassed = A({'href': '#'}, "Toggle passed tests"); var toggleFailed = A({'href': '#'}, "Toggle failed tests"); togglePassed.onclick = partial(SimpleTest.toggleByClass, 'test_ok'); toggleFailed.onclick = partial(SimpleTest.toggleByClass, 'test_not_ok'); var body = document.getElementsByTagName("body")[0]; var firstChild = body.childNodes[0]; var addNode; if (firstChild) { addNode = function (el) { body.insertBefore(el, firstChild); }; } else { addNode = function (el) { body.appendChild(el) }; } addNode(togglePassed); addNode(SPAN(null, " ")); addNode(toggleFailed); addNode(SimpleTest.report()); }; /** * Tells SimpleTest to don't finish the test when the document is loaded, * useful for asynchronous tests. * * When SimpleTest.waitForExplicitFinish is called, * explicit SimpleTest.finish() is required. **/ SimpleTest.waitForExplicitFinish = function () { SimpleTest._stopOnLoad = false; }; /** * Talks to the TestRunner if being ran on a iframe and the parent has a * TestRunner object. **/ SimpleTest.talkToRunner = function () { if (typeof(parent) != "undefined" && parent.TestRunner) { parent.TestRunner.testFinished(document); } }; /** * Finishes the tests. This is automatically called, except when * SimpleTest.waitForExplicitFinish() has been invoked. **/ SimpleTest.finish = function () { SimpleTest.showReport(); SimpleTest.talkToRunner(); }; addLoadEvent(function() { if (SimpleTest._stopOnLoad) { SimpleTest.finish(); } }); // --------------- Test.Builder/Test.More isDeeply() ----------------- SimpleTest.DNE = {dne: 'Does not exist'}; SimpleTest.LF = "\r\n"; SimpleTest._isRef = function (object) { var type = typeof(object); return type == 'object' || type == 'function'; }; SimpleTest._deepCheck = function (e1, e2, stack, seen) { var ok = false; // Either they're both references or both not. var sameRef = !(!SimpleTest._isRef(e1) ^ !SimpleTest._isRef(e2)); if (e1 == null && e2 == null) { ok = true; } else if (e1 != null ^ e2 != null) { ok = false; } else if (e1 == SimpleTest.DNE ^ e2 == SimpleTest.DNE) { ok = false; } else if (sameRef && e1 == e2) { // Handles primitives and any variables that reference the same // object, including functions. ok = true; } else if (SimpleTest.isa(e1, 'Array') && SimpleTest.isa(e2, 'Array')) { ok = SimpleTest._eqArray(e1, e2, stack, seen); } else if (typeof e1 == "object" && typeof e2 == "object") { ok = SimpleTest._eqAssoc(e1, e2, stack, seen); } else { // If we get here, they're not the same (function references must // always simply rererence the same function). stack.push({ vals: [e1, e2] }); ok = false; } return ok; }; SimpleTest._eqArray = function (a1, a2, stack, seen) { // Return if they're the same object. if (a1 == a2) return true; // JavaScript objects have no unique identifiers, so we have to store // references to them all in an array, and then compare the references // directly. It's slow, but probably won't be much of an issue in // practice. Start by making a local copy of the array to as to avoid // confusing a reference seen more than once (such as [a, a]) for a // circular reference. for (var j = 0; j < seen.length; j++) { if (seen[j][0] == a1) { return seen[j][1] == a2; } } // If we get here, we haven't seen a1 before, so store it with reference // to a2. seen.push([ a1, a2 ]); var ok = true; // Only examines enumerable attributes. Only works for numeric arrays! // Associative arrays return 0. So call _eqAssoc() for them, instead. var max = a1.length > a2.length ? a1.length : a2.length; if (max == 0) return SimpleTest._eqAssoc(a1, a2, stack, seen); for (var i = 0; i < max; i++) { var e1 = i > a1.length - 1 ? SimpleTest.DNE : a1[i]; var e2 = i > a2.length - 1 ? SimpleTest.DNE : a2[i]; stack.push({ type: 'Array', idx: i, vals: [e1, e2] }); if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) { stack.pop(); } else { break; } } return ok; }; SimpleTest._eqAssoc = function (o1, o2, stack, seen) { // Return if they're the same object. if (o1 == o2) return true; // JavaScript objects have no unique identifiers, so we have to store // references to them all in an array, and then compare the references // directly. It's slow, but probably won't be much of an issue in // practice. Start by making a local copy of the array to as to avoid // confusing a reference seen more than once (such as [a, a]) for a // circular reference. seen = seen.slice(0); for (var j = 0; j < seen.length; j++) { if (seen[j][0] == o1) { return seen[j][1] == o2; } } // If we get here, we haven't seen o1 before, so store it with reference // to o2. seen.push([ o1, o2 ]); // They should be of the same class. var ok = true; // Only examines enumerable attributes. var o1Size = 0; for (var i in o1) o1Size++; var o2Size = 0; for (var i in o2) o2Size++; var bigger = o1Size > o2Size ? o1 : o2; for (var i in bigger) { var e1 = o1[i] == undefined ? SimpleTest.DNE : o1[i]; var e2 = o2[i] == undefined ? SimpleTest.DNE : o2[i]; stack.push({ type: 'Object', idx: i, vals: [e1, e2] }); if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) { stack.pop(); } else { break; } } return ok; }; SimpleTest._formatStack = function (stack) { var variable = '$Foo'; for (var i = 0; i < stack.length; i++) { var entry = stack[i]; var type = entry['type']; var idx = entry['idx']; if (idx != null) { if (/^\d+$/.test(idx)) { // Numeric array index. variable += '[' + idx + ']'; } else { // Associative array index. idx = idx.replace("'", "\\'"); variable += "['" + idx + "']"; } } } var vals = stack[stack.length-1]['vals'].slice(0, 2); var vars = [ variable.replace('$Foo', 'got'), variable.replace('$Foo', 'expected') ]; var out = "Structures begin differing at:" + SimpleTest.LF; for (var i = 0; i < vals.length; i++) { var val = vals[i]; if (val == null) { val = 'undefined'; } else { val == SimpleTest.DNE ? "Does not exist" : "'" + val + "'"; } } out += vars[0] + ' = ' + vals[0] + SimpleTest.LF; out += vars[1] + ' = ' + vals[1] + SimpleTest.LF; return ' ' + out; }; SimpleTest.isDeeply = function (it, as, name) { var ok; // ^ is the XOR operator. if (SimpleTest._isRef(it) ^ SimpleTest._isRef(as)) { // One's a reference, one isn't. ok = false; } else if (!SimpleTest._isRef(it) && !SimpleTest._isRef(as)) { // Neither is an object. ok = SimpleTest.is(it, as, name); } else { // We have two objects. Do a deep comparison. var stack = [], seen = []; if ( SimpleTest._deepCheck(it, as, stack, seen)) { ok = SimpleTest.ok(true, name); } else { ok = SimpleTest.ok(false, name, SimpleTest._formatStack(stack)); } } return ok; }; SimpleTest.typeOf = function (object) { var c = Object.prototype.toString.apply(object); var name = c.substring(8, c.length - 1); if (name != 'Object') return name; // It may be a non-core class. Try to extract the class name from // the constructor function. This may not work in all implementations. if (/function ([^(\s]+)/.test(Function.toString.call(object.constructor))) { return RegExp.$1; } // No idea. :-( return name; }; SimpleTest.isa = function (object, clas) { return SimpleTest.typeOf(object) == clas; }; // Global symbols: var ok = SimpleTest.ok; var is = SimpleTest.is; var isDeeply = SimpleTest.isDeeply; MochiKit-1.4.2/tests/SimpleTest/TestRunner.js0000660000175000017500000001061211102215550020167 0ustar scottscott/** * TestRunner: A test runner for SimpleTest * TODO: * * * Avoid moving iframes: That causes reloads on mozilla and opera. * * **/ var TestRunner = {}; TestRunner.logEnabled = false; TestRunner._iframes = {}; TestRunner._iframeDocuments = {}; TestRunner._iframeRows = {}; TestRunner._currentTest = 0; TestRunner._urls = []; TestRunner._testsDiv = DIV(); TestRunner._progressDiv = DIV(); TestRunner._summaryDiv = DIV(null, H1(null, "Tests Summary"), TABLE(null, THEAD(null, TR(null, TH(null, "Test"), TH(null, "Passed"), TH(null, "Failed") ) ), TBODY() ) ); /** * This function is called after generating the summary. **/ TestRunner.onComplete = null; /** * If logEnabled is true, this is the logger that will be used. **/ TestRunner.logger = MochiKit.Logging.logger; /** * Toggle element visibility **/ TestRunner._toggle = function(el) { if (el.className == "noshow") { el.className = ""; el.style.cssText = ""; } else { el.className = "noshow"; el.style.cssText = "width:0px; height:0px; border:0px;"; } }; /** * Creates the iframe that contains a test **/ TestRunner._makeIframe = function (url) { var iframe = document.createElement('iframe'); iframe.src = url; iframe.name = url; iframe.width = "500"; var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0]; var tr = TR(null, TD({'colspan': '3'}, iframe)); iframe._row = tr; tbody.appendChild(tr); return iframe; }; /** * TestRunner entry point. * * The arguments are the URLs of the test to be ran. * **/ TestRunner.runTests = function (/*url...*/) { if (TestRunner.logEnabled) TestRunner.logger.log("SimpleTest START"); var body = document.getElementsByTagName("body")[0]; appendChildNodes(body, TestRunner._testsDiv, TestRunner._progressDiv, TestRunner._summaryDiv ); for (var i = 0; i < arguments.length; i++) { TestRunner._urls.push(arguments[i]); } TestRunner.runNextTest(); }; /** * Run the next test. If no test remains, calls makeSummary **/ TestRunner.runNextTest = function() { if (TestRunner._currentTest < TestRunner._urls.length) { var url = TestRunner._urls[TestRunner._currentTest]; var progress = SPAN(null, "Running ", A({href:url}, url), "..." ); if (TestRunner.logEnabled) TestRunner.logger.log(scrapeText(progress)); TestRunner._progressDiv.appendChild(progress); TestRunner._iframes[url] = TestRunner._makeIframe(url); } else { TestRunner.makeSummary(); if (TestRunner.onComplete) TestRunner.onComplete(); } }; /** * This stub is called by SimpleTest when a test is finished. **/ TestRunner.testFinished = function (doc) { appendChildNodes(TestRunner._progressDiv, SPAN(null, "Done"), BR()); var finishedURL = TestRunner._urls[TestRunner._currentTest]; if (TestRunner.logEnabled) TestRunner.logger.debug("SimpleTest finished " + finishedURL); TestRunner._iframeDocuments[finishedURL] = doc; // TestRunner._iframes[finishedURL].style.display = "none"; TestRunner._toggle(TestRunner._iframes[finishedURL]); TestRunner._currentTest++; TestRunner.runNextTest(); }; /** * Display the summary in the browser **/ TestRunner.makeSummary = function() { if (TestRunner.logEnabled) TestRunner.logger.log("SimpleTest FINISHED"); var rows = []; for (var url in TestRunner._iframeDocuments) { var doc = TestRunner._iframeDocuments[url]; var nOK = withDocument(doc, partial(getElementsByTagAndClassName, 'div', 'test_ok') ).length; var nNotOK = withDocument(doc, partial(getElementsByTagAndClassName, 'div', 'test_not_ok') ).length; var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]); var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])"; var row = TR( {'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}}, TD(null, url), TD(null, nOK), TD(null, nNotOK) ); row.onclick = toggle; var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0]; tbody.insertBefore(row, TestRunner._iframes[url]._row) } }; MochiKit-1.4.2/tests/test_MochiKit-Visual.html0000660000175000017500000001433111113647642020343 0ustar scottscott
elt1
elt3

MochiKit-1.4.2/tests/test_MochiKit-Format.html0000660000175000017500000000210011113647642020317 0ustar scottscott


MochiKit-1.4.2/tests/FakeJSAN.js0000660000175000017500000000203211102215552015306 0ustar scottscottvar JSAN = { global: this, use: function (module, symbols) { var components = module.split(/\./); var fn = components.join('/') + '.js'; var o = JSAN.global; var i, c; for (i = 0; i < components.length; i++) { o = o[components[i]]; if (typeof(o) == 'undefined') { break; } } if (typeof(o) != 'undefined') { return o; } load(fn); o = JSAN.global; for (i = 0; i < components.length; i++) { o = o[components[i]]; if (typeof(o) == 'undefined') { return undefined; } } if (!symbols) { var tags = o.EXPORT_TAGS; if (tags) { symbols = tags[':common'] || tags[':all']; } } if (symbols) { for (i = 0; i < symbols.length; i++) { c = symbols[i]; JSAN.global[c] = o[c]; } } return o; } }; MochiKit-1.4.2/tests/cli.js0000660000175000017500000000026311102215552014537 0ustar scottscottMochiKit = {__export__: true}; load('tests/FakeJSAN.js') JSAN.use('MochiKit.MockDOM'); var window = this; var document = MochiKit.MockDOM.document; JSAN.use('MochiKit.MochiKit'); MochiKit-1.4.2/tests/test_MochiKit-JSAN.html0000660000175000017500000000137111113647642017633 0ustar scottscott

MochiKit-1.4.2/tests/test_MochiKit-DOM-Safari.html0000660000175000017500000000260011113647642020716 0ustar scottscott

MochiKit-1.4.2/tests/standalone.js0000660000175000017500000000065111102215552016121 0ustar scottscottload('tests/cli.js'); JSAN.use('MochiKit.Test'); print("[[ MochiKit.Base ]]"); runTests('tests.test_Base'); print("[[ MochiKit.Color ]]"); runTests('tests.test_Color'); print("[[ MochiKit.DateTime ]]"); runTests('tests.test_DateTime'); print("[[ MochiKit.Format ]]"); runTests('tests.test_Format'); print("[[ MochiKit.Iter ]]"); runTests('tests.test_Iter'); print("[[ MochiKit.Logging ]]"); runTests('tests.test_Logging'); MochiKit-1.4.2/tests/test_MochiKit-Async.json0000660000175000017500000000002111102215552020136 0ustar scottscott{"passed": true} MochiKit-1.4.2/tests/test_DragAndDrop.js0000660000175000017500000000230311102215552017151 0ustar scottscottif (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); } if (typeof(tests) == 'undefined') { tests = {}; } tests.test_DragAndDrop = function (t) { var drag1 = new MochiKit.DragAndDrop.Draggable('drag1', {'revert': true, 'ghosting': true}); var drop1 = new MochiKit.DragAndDrop.Droppable('drop1', {'hoverclass': 'drop-hover'}); drop1.activate(); t.is(hasElementClass('drop1', 'drop-hover'), true, "hoverclass ok"); drop1.deactivate(); t.is(hasElementClass('drop1', 'drop-hover'), false, "remove hoverclass ok"); drop1.destroy(); t.is( isEmpty(MochiKit.DragAndDrop.Droppables.drops), true, "Unregister droppable ok"); var onhover = function (element) { t.is(element, getElement('drag1'), 'onhover ok'); }; var drop2 = new MochiKit.DragAndDrop.Droppable('drop1', {'onhover': onhover}); var pos = getElementPosition('drop1'); pos = {"x": pos.x + 5, "y": pos.y + 5}; MochiKit.DragAndDrop.Droppables.show({"page": pos}, getElement('drag1')); drag1.destroy(); t.is( isEmpty(MochiKit.DragAndDrop.Draggables.drops), true, "Unregister draggable ok"); }; MochiKit-1.4.2/tests/test_Logging.js0000660000175000017500000000626211102215552016422 0ustar scottscottif (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Logging'); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Logging'); } if (typeof(tests) == 'undefined') { tests = {}; } tests.test_Logging = function (t) { // just in case logger.clear(); t.is( logLevelAtLeast('DEBUG')('INFO'), false, 'logLevelAtLeast false' ); t.is( logLevelAtLeast('WARNING')('INFO'), false, 'logLevelAtLeast true' ); t.ok( logger instanceof Logger, "global logger installed" ); var allMessages = []; logger.addListener("allMessages", null, bind(allMessages.push, allMessages)); var fatalMessages = []; logger.addListener("fatalMessages", "FATAL", bind(fatalMessages.push, fatalMessages)); var firstTwo = []; logger.addListener("firstTwo", null, bind(firstTwo.push, firstTwo)); log("foo"); var msgs = logger.getMessages(); t.is( msgs.length, 1, 'global log() put one message in queue' ); t.is( compare(allMessages, msgs), 0, "allMessages listener" ); var msg = msgs.pop(); t.is( compare(msg.info, ["foo"]), 0, "info matches" ); t.is( msg.level, "INFO", "level matches" ); logDebug("debugFoo"); t.is( msgs.length, 0, 'getMessages() returns copy' ); msgs = logger.getMessages(); t.is( compare(allMessages, msgs), 0, "allMessages listener" ); t.is( msgs.length, 2, 'logDebug()' ); msg = msgs.pop(); t.is( compare(msg.info, ["debugFoo"]), 0, "info matches" ); t.is( msg.level, "DEBUG", "level matches" ); logger.removeListener("firstTwo"); logError("errorFoo"); msgs = logger.getMessages(); t.is( compare(allMessages, msgs), 0, "allMessages listener" ); t.is( msgs.length, 3, 'logError()' ); msg = msgs.pop(); t.is( compare(msg.info, ["errorFoo"]), 0, "info matches" ); t.is( msg.level, "ERROR", "level matches" ); logWarning("warningFoo"); msgs = logger.getMessages(); t.is( compare(allMessages, msgs), 0, "allMessages listener" ); t.is( msgs.length, 4, 'logWarning()' ); msg = msgs.pop(); t.is( compare(msg.info, ["warningFoo"]), 0, "info matches" ); t.is( msg.level, "WARNING", "level matches" ); logFatal("fatalFoo"); msgs = logger.getMessages(); t.is( compare(allMessages, msgs), 0, "allMessages listener" ); t.is( msgs.length, 5, 'logFatal()' ); msg = msgs.pop(); t.is( compare(fatalMessages, [msg]), 0, "fatalMessages listener" ); t.is( compare(msg.info, ["fatalFoo"]), 0, "info matches" ); t.is( msg.level, "FATAL", "level matches" ); msgs = logger.getMessages(1); t.is( compare(fatalMessages, msgs), 0, "getMessages with limit returns latest" ); logger.removeListener("allMessages"); logger.removeListener("fatalMessages"); t.is( compare(firstTwo, logger.getMessages().slice(0, 2)), 0, "firstTwo" ); logger.clear(); msgs = logger.getMessages(); t.is(msgs.length, 0, "clear removes existing messages"); logger.baseLog(LogLevel.INFO, 'infoFoo'); msg = logger.getMessages().pop(); t.is(msg.level, "INFO", "baseLog converts level") logger.baseLog(45, 'errorFoo'); msg = logger.getMessages().pop(); t.is(msg.level, "ERROR", "baseLog converts ad-hoc level") }; MochiKit-1.4.2/tests/test_Format.js0000660000175000017500000001155311102215552016263 0ustar scottscottif (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Format'); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Format'); } if (typeof(tests) == 'undefined') { tests = {}; } tests.test_Format = function (t) { t.is( truncToFixed(0.1234, 3), "0.123", "truncToFixed truncate" ); t.is( truncToFixed(0.12, 3), "0.120", "truncToFixed trailing zeros" ); t.is( truncToFixed(0.15, 1), "0.1", "truncToFixed no round" ); t.is( truncToFixed(0.15, 0), "0", "truncToFixed zero (edge case)" ); t.is( truncToFixed(568.80, 2), "568.80", "truncToFixed 568.80, floating-point error" ); t.is( truncToFixed(1.23e+20, 2), "123000000000000000000.00", "truncToFixed 1.23e+20" ); t.is( truncToFixed(-1.23e+20, 2), "-123000000000000000000.00", "truncToFixed -1.23e+20" ); t.is( truncToFixed(1.23e-10, 2), "0.00", "truncToFixed 1.23e-10" ); t.is( roundToFixed(0.1234, 3), "0.123", "roundToFixed truncate" ); t.is( roundToFixed(0.12, 3), "0.120", "roundToFixed trailing zeros" ); t.is( roundToFixed(0.15, 1), "0.2", "roundToFixed round" ); t.is( roundToFixed(0.15, 0), "0", "roundToFixed zero (edge case)" ); t.is( roundToFixed(568.80, 2), "568.80", "roundToFixed 568.80, floating-point error" ); t.is( twoDigitFloat(-0.1234), "-0.12", "twoDigitFloat -0.1234 correct"); t.is( twoDigitFloat(-0.1), "-0.1", "twoDigitFloat -0.1 correct"); t.is( twoDigitFloat(-0), "0", "twoDigitFloat -0 correct"); t.is( twoDigitFloat(0), "0", "twoDigitFloat 0 correct"); t.is( twoDigitFloat(1), "1", "twoDigitFloat 1 correct"); t.is( twoDigitFloat(1.0), "1", "twoDigitFloat 1.0 correct"); t.is( twoDigitFloat(1.2), "1.2", "twoDigitFloat 1.2 correct"); t.is( twoDigitFloat(1.234), "1.23", "twoDigitFloat 1.234 correct"); t.is( twoDigitFloat(0.23), "0.23", "twoDigitFloat 0.23 correct"); t.is( twoDigitFloat(0.01), "0.01", "twoDigitFloat 0.01 correct"); t.is( twoDigitFloat(568.80), "568.8", "twoDigitFloat, floating-point error"); t.is( percentFormat(123), "12300%", "percentFormat 123 correct"); t.is( percentFormat(1.23), "123%", "percentFormat 123 correct"); t.is( twoDigitAverage(1, 0), "0", "twoDigitAverage dbz correct"); t.is( twoDigitAverage(1, 1), "1", "twoDigitAverage 1 correct"); t.is( twoDigitAverage(1, 10), "0.1", "twoDigitAverage .1 correct"); function reprIs(a, b) { arguments[0] = repr(a); arguments[1] = repr(b); t.is.apply(this, arguments); } reprIs( lstrip("\r\t\n foo \n\t\r"), "foo \n\t\r", "lstrip whitespace chars" ); reprIs( rstrip("\r\t\n foo \n\t\r"), "\r\t\n foo", "rstrip whitespace chars" ); reprIs( strip("\r\t\n foo \n\t\r"), "foo", "strip whitespace chars" ); reprIs( lstrip("\r\n\t \r", "\r"), "\n\t \r", "lstrip custom chars" ); reprIs( rstrip("\r\n\t \r", "\r"), "\r\n\t ", "rstrip custom chars" ); reprIs( strip("\r\n\t \r", "\r"), "\n\t ", "strip custom chars" ); var nf = numberFormatter("$###,###.00 footer"); t.is( nf(1000.1), "$1,000.10 footer", "trailing zeros" ); t.is( nf(1000000.1), "$1,000,000.10 footer", "two seps" ); t.is( nf(100), "$100.00 footer", "shorter than sep" ); t.is( nf(100.555), "$100.56 footer", "rounding" ); t.is( nf(-100.555), "$-100.56 footer", "default neg" ); nf = numberFormatter("-$###,###.00"); t.is( nf(-100.555), "-$100.56", "custom neg" ); nf = numberFormatter("0000.0000"); t.is( nf(0), "0000.0000", "leading and trailing" ); t.is( nf(1.1), "0001.1000", "leading and trailing" ); t.is( nf(12345.12345), "12345.1235", "no need for leading/trailing" ); nf = numberFormatter("0000.0000"); t.is( nf("taco"), "", "default placeholder" ); nf = numberFormatter("###,###.00", "foo", "de_DE"); t.is( nf("taco"), "foo", "custom placeholder" ); t.is( nf(12345.12345), "12.345,12", "de_DE locale" ); nf = numberFormatter("#%"); t.is( nf(1), "100%", "trivial percent" ); t.is( nf(0.55), "55%", "percent" ); var customLocale = { separator: " apples and ", decimal: " bagels at ", percent: "am for breakfast"}; var customFormatter = numberFormatter("###,###.0%", "No breakfast", customLocale); t.is( customFormatter(23.458), "2 apples and 345 bagels at 8am for breakfast", "custom locale" ); nf = numberFormatter("###,###"); t.is( nf(123), "123", "large number format" ); t.is( nf(1234), "1,234", "large number format" ); t.is( nf(12345), "12,345", "large number format" ); t.is( nf(123456), "123,456", "large number format" ); t.is( nf(1234567), "1,234,567", "large number format" ); t.is( nf(12345678), "12,345,678", "large number format" ); t.is( nf(123456789), "123,456,789", "large number format" ); t.is( nf(1234567890), "1,234,567,890", "large number format" ); t.is( nf(12345678901), "12,345,678,901", "large number format" ); t.is( nf(123456789012), "123,456,789,012", "large number format" ); }; MochiKit-1.4.2/tests/test_MochiKit-DOM.html0000660000175000017500000004006611113647642017523 0ustar scottscott
child

MochiKit-1.4.2/tests/test_MochiKit-DragAndDrop.html0000660000175000017500000000310211113647642021217 0ustar scottscott
drag1
drop1


MochiKit-1.4.2/doc/0000755000175000017500000000000011136470264013050 5ustar scottscottMochiKit-1.4.2/doc/js/0000755000175000017500000000000011136470264013464 5ustar scottscottMochiKit-1.4.2/doc/js/toc.js0000660000175000017500000000713511102215564014604 0ustar scottscottfunction function_ref(fn) { return A({"href": fn[1], "class": "mochiref reference"}, fn[0], BR()); }; function toggle_docs() { toggleElementClass("invisible", "show_index", "function_index"); return false; }; function create_toc() { if (getElement("distribution")) { return global_index(); } if (getElement("api-reference")) { return module_index(); } }; function doXHTMLRequest(url) { var d = doXHR(url, {mimeType: 'text/xml'}); return d.addCallback(function (res) { if (res.responseXML.documentElement) { return res.responseXML.documentElement; } else { var container = document.createElement('div'); container.innerHTML = res.responseText; return container; } }); }; function load_request(href, div, doc) { var functions = withDocument(doc, spider_doc); forEach(functions, function (func) { // fix anchors if (func[1].charAt(0) == "#") { func[1] = href + func[1]; } else if (func[1].lastIndexOf("#") != -1) { func[1] = href + "#" + func[1].split("#")[1]; } }); var showLink = A({"class": "force-pointer"}, "[+]"); var hideLink = A({"class": "force-pointer"}, "[\u2013]"); var functionIndex = DIV({"id": "function_index", "class": "invisible"}, hideLink, P(null, map(function_ref, functions)) ); var toggleFunc = function (e) { toggleElementClass("invisible", showLink, functionIndex); }; connect(showLink, "onclick", toggleFunc); connect(hideLink, "onclick", toggleFunc); replaceChildNodes(div, showLink, functionIndex ); return [showLink, toggleFunc]; }; function global_index() { var distList = getElementsByTagAndClassName("ul")[0]; var bullets = getElementsByTagAndClassName("li", null, distList); var lst = []; for (var i = 0; i < bullets.length; i++) { var tag = bullets[i]; var firstLink = getElementsByTagAndClassName("a", "mochiref", tag)[0]; var href = getNodeAttribute(firstLink, "href"); var div = DIV(null, "[\u2026]"); appendChildNodes(tag, BR(), div); lst.push(doXHTMLRequest(href).addCallback(load_request, href, div)); } var loadingNode = DIV(null, "[loading index\u2026]"); distList.parentNode.insertBefore(P(null, loadingNode), distList); var dl = gatherResults(lst).addCallback(function (res) { var toggleFunc = function (e) { for (var i = 0; i < res.length; i++) { var item = res[i]; if (!hasElementClass(item[0], "invisible")) { item[1](); } } }; var node = A({"class": "force-pointer"}, "[click to expand all]"); swapDOM(loadingNode, node); connect(node, "onclick", toggleFunc); }); }; function spider_doc() { return map( function (tag) { return [scrapeText(tag), getNodeAttribute(tag, "href")]; }, getElementsByTagAndClassName("a", "mochidef") ); }; function module_index() { var sections = getElementsByTagAndClassName("div", "section"); var ptr = sections[1]; var ref = DIV({"class": "section"}, H1(null, "Function Index"), A({"id": "show_index", "href": "#", "onclick": toggle_docs}, "[show]"), DIV({"id": "function_index", "class": "invisible"}, A({"href":"#", "onclick": toggle_docs}, "[hide]"), P(null, map(function_ref, spider_doc())))); ptr.parentNode.insertBefore(ref, ptr); }; connect(window, 'onload', create_toc); MochiKit-1.4.2/doc/rst/0000755000175000017500000000000011136470264013660 5ustar scottscottMochiKit-1.4.2/doc/rst/MochiKit/0000755000175000017500000000000011136470264015367 5ustar scottscottMochiKit-1.4.2/doc/rst/MochiKit/Async.rst0000660000175000017500000005715011102215564017175 0ustar scottscott.. title:: MochiKit.Async - manage asynchronous tasks Name ==== MochiKit.Async - manage asynchronous tasks Synopsis ======== :: var url = "/src/b/bo/bob/MochiKit.Async/META.json"; /* META.json looks something like this: {"name": "MochiKit", "version": "0.5"} */ var d = loadJSONDoc(url); var gotMetadata = function (meta) { if (MochiKit.Async.VERSION == meta.version) { alert("You have the newest MochiKit.Async!"); } else { alert("MochiKit.Async " + meta.version + " is available, upgrade!"); } }; var metadataFetchFailed = function (err) { alert("The metadata for MochiKit.Async could not be fetched :("); }; d.addCallbacks(gotMetadata, metadataFetchFailed); Description =========== MochiKit.Async provides facilities to manage asynchronous (as in AJAX [1]_) tasks. The model for asynchronous computation used in this module is heavily inspired by Twisted [2]_. Dependencies ============ - :mochiref:`MochiKit.Base` Security Concerns ================= The current implementation of evalJSONRequest does no input validation. Invalid JSON can execute arbitrary JavaScript code in the client. This isn't normally a concern because of the same-origin policy in web browsers; the server is already sending arbitrary code to the client (your program!). While this isn't directly relevant to MochiKit, server-side code that produces JSON should consider potential cross-site request forgery. Currently known exploits require a JSON array to be the outer-most object, and the data to be leaked must be known keys in objects contained by that array:: [{"some_known_key": "this can be leaked"}, "but not this"] This exploit does not apply to the most common usage of JSON, sending an object:: {"some_known_key": "this can't be leaked"} There are several ways to avoid this, here are a few: * Use some non-standard addition to JSON that adds constructs to prevent script tag parsing, such as wrapping the data in a comment or an infinite loop. MochiKit supports comment-wrapped JSON, but it's up to the server to send it that way. * Require some kind of authentication token in the URL. * Allow only POST requests to access sensitive JSON. * Only send JSON objects, not arrays. JSON objects aren't valid JavaScript syntax on their own without parentheses. Overview ======== Deferred -------- The Deferred constructor encapsulates a single value that is not available yet. The most important example of this in the context of a web browser would be an ``XMLHttpRequest`` to a server. The importance of the Deferred is that it allows a consistent API to be exposed for all asynchronous computations that occur exactly once. The producer of the Deferred is responsible for doing all of the complicated work behind the scenes. This often means waiting for a timer to fire, or waiting for an event (e.g. ``onreadystatechange`` of ``XMLHttpRequest``). It could also be coordinating several events (e.g. ``XMLHttpRequest`` with a timeout, or several Deferreds (e.g. fetching a set of XML documents that should be processed at the same time). Since these sorts of tasks do not respond immediately, the producer of the Deferred does the following steps before returning to the consumer: 1. Create a ``new`` :mochiref:`Deferred();` object and keep a reference to it, because it will be needed later when the value is ready. 2. Setup the conditions to create the value requested (e.g. create a new ``XMLHttpRequest``, set its ``onreadystatechange``). 3. Return the :mochiref:`Deferred` object. Since the value is not yet ready, the consumer attaches a function to the Deferred that will be called when the value is ready. This is not unlike ``setTimeout``, or other similar facilities you may already be familiar with. The consumer can also attach an "errback" to the :mochiref:`Deferred`, which is a callback for error handling. When the value is ready, the producer simply calls ``myDeferred.callback(theValue)``. If an error occurred, it should call ``myDeferred.errback(theValue)`` instead. As soon as this happens, the callback that the consumer attached to the :mochiref:`Deferred` is called with ``theValue`` as the only argument. There are quite a few additional "advanced" features baked into :mochiref:`Deferred`, such as cancellation and callback chains, so take a look at the API reference if you would like to know more! API Reference ============= Errors ------ :mochidef:`AlreadyCalledError`: Thrown by a :mochiref:`Deferred` if ``.callback`` or ``.errback`` are called more than once. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`BrowserComplianceError`: Thrown when the JavaScript runtime is not capable of performing the given function. Currently, this happens if the browser does not support ``XMLHttpRequest``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`CancelledError`: Thrown by a :mochiref:`Deferred` when it is cancelled, unless a canceller is present and throws something else. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`GenericError`: Results passed to ``.fail`` or ``.errback`` of a :mochiref:`Deferred` are wrapped by this ``Error`` if ``!(result instanceof Error)``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`XMLHttpRequestError`: Thrown when an ``XMLHttpRequest`` does not complete successfully for any reason. The ``req`` property of the error is the failed ``XMLHttpRequest`` object, and for convenience the ``number`` property corresponds to ``req.status``. *Availability*: Available in MochiKit 1.3.1+ Constructors ------------ :mochidef:`Deferred()`: Encapsulates a sequence of callbacks in response to a value that may not yet be available. This is modeled after the Deferred class from Twisted [3]_. .. _`Twisted`: http://twistedmatrix.com/ Why do we want this? JavaScript has no threads, and even if it did, threads are hard. Deferreds are a way of abstracting non-blocking events, such as the final response to an ``XMLHttpRequest``. The sequence of callbacks is internally represented as a list of 2-tuples containing the callback/errback pair. For example, the following call sequence:: var d = new Deferred(); d.addCallback(myCallback); d.addErrback(myErrback); d.addBoth(myBoth); d.addCallbacks(myCallback, myErrback); is translated into a :mochiref:`Deferred` with the following internal representation:: [ [myCallback, null], [null, myErrback], [myBoth, myBoth], [myCallback, myErrback] ] The :mochiref:`Deferred` also keeps track of its current status (fired). Its status may be one of the following three values: ===== ================================ Value Condition ===== ================================ -1 no value yet (initial condition) 0 success 1 error ===== ================================ A :mochiref:`Deferred` will be in the error state if one of the following conditions are met: 1. The result given to callback or errback is "``instanceof Error``" 2. The callback or errback threw while executing. If the thrown object is not ``instanceof Error``, it will be wrapped with :mochiref:`GenericError`. Otherwise, the :mochiref:`Deferred` will be in the success state. The state of the :mochiref:`Deferred` determines the next element in the callback sequence to run. When a callback or errback occurs with the example deferred chain, something equivalent to the following will happen (imagine that exceptions are caught and returned as-is):: // d.callback(result) or d.errback(result) if (!(result instanceof Error)) { result = myCallback(result); } if (result instanceof Error) { result = myErrback(result); } result = myBoth(result); if (result instanceof Error) { result = myErrback(result); } else { result = myCallback(result); } The result is then stored away in case another step is added to the callback sequence. Since the :mochiref:`Deferred` already has a value available, any new callbacks added will be called immediately. There are two other "advanced" details about this implementation that are useful: Callbacks are allowed to return :mochiref:`Deferred` instances, so you can build complicated sequences of events with (relative) ease. The creator of the :mochiref:`Deferred` may specify a canceller. The canceller is a function that will be called if :mochiref:`Deferred.prototype.cancel` is called before the :mochiref:`Deferred` fires. You can use this to allow an ``XMLHttpRequest`` to be cleanly cancelled, for example. Note that cancel will fire the :mochiref:`Deferred` with a :mochiref:`CancelledError` (unless your canceller throws or returns a different ``Error``), so errbacks should be prepared to handle that ``Error`` gracefully for cancellable :mochiref:`Deferred` instances. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Deferred.prototype.addBoth(func)`: Add the same function as both a callback and an errback as the next element on the callback sequence. This is useful for code that you want to guarantee to run, e.g. a finalizer. If additional arguments are given, then ``func`` will be replaced with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This differs from `Twisted`_, because the result of the callback or errback will be the *last* argument passed to ``func``. If ``func`` returns a :mochiref:`Deferred`, then it will be chained (its value or error will be passed to the next callback). Note that once the returned ``Deferred`` is chained, it can no longer accept new callbacks. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Deferred.prototype.addCallback(func[, ...])`: Add a single callback to the end of the callback sequence. If additional arguments are given, then ``func`` will be replaced with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This differs from `Twisted`_, because the result of the callback will be the *last* argument passed to ``func``. If ``func`` returns a :mochiref:`Deferred`, then it will be chained (its value or error will be passed to the next callback). Note that once the returned ``Deferred`` is chained, it can no longer accept new callbacks. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Deferred.prototype.addCallbacks(callback, errback)`: Add separate callback and errback to the end of the callback sequence. Either callback or errback may be ``null``, but not both. If ``callback`` or ``errback`` returns a :mochiref:`Deferred`, then it will be chained (its value or error will be passed to the next callback). Note that once the returned ``Deferred`` is chained, it can no longer accept new callbacks. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Deferred.prototype.addErrback(func)`: Add a single errback to the end of the callback sequence. If additional arguments are given, then ``func`` will be replaced with :mochiref:`MochiKit.Base.partial.apply(null, arguments)`. This differs from `Twisted`_, because the result of the errback will be the *last* argument passed to ``func``. If ``func`` returns a :mochiref:`Deferred`, then it will be chained (its value or error will be passed to the next callback). Note that once the returned ``Deferred`` is chained, it can no longer accept new callbacks. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Deferred.prototype.callback([result])`: Begin the callback sequence with a non-``Error`` result. Result may be any value except for a :mochiref:`Deferred`. Either ``.callback`` or ``.errback`` should be called exactly once on a :mochiref:`Deferred`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Deferred.prototype.cancel()`: Cancels a :mochiref:`Deferred` that has not yet received a value, or is waiting on another :mochiref:`Deferred` as its value. If a canceller is defined, the canceller is called. If the canceller did not return an ``Error``, or there was no canceller, then the errback chain is started with :mochiref:`CancelledError`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Deferred.prototype.errback([result])`: Begin the callback sequence with an error result. Result may be any value except for a :mochiref:`Deferred`, but if ``!(result instanceof Error)``, it will be wrapped with :mochiref:`GenericError`. Either ``.callback`` or ``.errback`` should be called exactly once on a :mochidef:`Deferred`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`DeferredLock()`: A lock for asynchronous systems. The ``locked`` property of a :mochiref:`DeferredLock` will be ``true`` if it locked, ``false`` otherwise. Do not change this property. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`DeferredLock.prototype.acquire()`: Attempt to acquire the lock. Returns a :mochiref:`Deferred` that fires on lock acquisition with the :mochiref:`DeferredLock` as the value. If the lock is locked, then the :mochiref:`Deferred` goes into a waiting list. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`DeferredLock.prototype.release()`: Release the lock. If there is a waiting list, then the first :mochiref:`Deferred` in that waiting list will be called back. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller])`: Combine a list of :mochiref:`Deferred` into one. Track the callbacks and return a list of (success, result) tuples, 'success' being a boolean indicating whether result is a normal result or an error. Once created, you have access to all :mochiref:`Deferred` methods, like addCallback, addErrback, addBoth. The behaviour can be changed by the following options: ``fireOnOneCallback``: Flag for launching the callback once the first Deferred of the list has returned. ``fireOnOneErrback``: Flag for calling the errback at the first error of a Deferred. ``consumeErrors``: Flag indicating that any errors raised in the Deferreds should be consumed by the DeferredList. Example:: // We need to fetch data from 2 different urls var d1 = loadJSONDoc(url1); var d2 = loadJSONDoc(url2); var l1 = new DeferredList([d1, d2], false, false, true); l1.addCallback(function (resultList) { MochiKit.Base.map(function (result) { if (result[0]) { alert("Data is here: " + result[1]); } else { alert("Got an error: " + result[1]); } }, resultList); }); *Availability*: Available in MochiKit 1.3.1+ Functions --------- :mochidef:`callLater(seconds, func[, args...])`: Call ``func(args...)`` after at least ``seconds`` seconds have elapsed. This is a convenience method for:: func = partial.apply(extend(null, arguments, 1)); return wait(seconds).addCallback(function (res) { return func() }); Returns a cancellable :mochiref:`Deferred`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`doXHR(url[, {option: value, ...}])`: Perform a customized ``XMLHttpRequest`` and wrap it with a :mochiref:`Deferred` that may be cancelled. Note that only ``200`` (OK), ``201`` (CREATED), ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered success codes. All other status codes will result in an errback with an ``XMLHttpRequestError``. ``url``: The URL for this request. The following options are currently accepted: ``method``: The HTTP method. Default is ``'GET'``. ``sendContent``: The content to send (e.g. with POST). Default is no content. ``queryString``: If present it will be used to build a query string to append to the url using :mochiref:`MochiKit.Base.queryString`. Default is no query string. ``username``: The username for the request. Default is no username. ``password``: The password for the request. Default is no password. ``headers``: Additional headers to set in the request, either as an object such as ``{'Accept': 'text/xml'}`` or as an Array of 2-Arrays ``[['Accept', 'text/xml']]``. Default is no additional headers. ``mimeType``: An override mime type. The typical use of this is to pass 'text/xml' to force XMLHttpRequest to attempt to parse responseXML. Default is no override. *returns*: :mochiref:`Deferred` that will callback with the ``XMLHttpRequest`` instance on success *Availability*: Available in MochiKit 1.4+. :mochidef:`doSimpleXMLHttpRequest(url[, queryArguments...])`: Perform a simple ``XMLHttpRequest`` and wrap it with a :mochiref:`Deferred` that may be cancelled. Note that only ``200`` (OK), ``201`` (CREATED), ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered success codes. All other status codes will result in an errback with an ``XMLHttpRequestError``. ``url``: The URL to GET ``queryArguments``: If this function is called with more than one argument, a ``"?"`` and the result of :mochiref:`MochiKit.Base.queryString` with the rest of the arguments are appended to the URL. For example, this will do a GET request to the URL ``http://example.com?bar=baz``:: doSimpleXMLHttpRequest("http://example.com", {bar: "baz"}); *returns*: :mochiref:`Deferred` that will callback with the ``XMLHttpRequest`` instance on success *Availability*: Available in MochiKit 1.3.1+. Support for 201 and 204 were added in MochiKit 1.4. :mochidef:`evalJSONRequest(req)`: Evaluate a JSON [4]_ ``XMLHttpRequest`` ``req``: The request whose ``.responseText`` property is to be evaluated. If the JSON is wrapped in a comment, the comment will be stripped before evaluation. *returns*: A JavaScript object *Availability*: Available in MochiKit 1.3.1+ :mochidef:`fail([result])`: Return a :mochiref:`Deferred` that has already had ``.errback(result)`` called. See ``succeed`` documentation for rationale. ``result``: The result to give to :mochiref:`Deferred.prototype.errback(result)`. *returns*: A ``new`` :mochiref:`Deferred()` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`gatherResults(deferreds)`: A convenience function that returns a :mochiref:`DeferredList` from the given ``Array`` of :mochiref:`Deferred` instances that will callback with an ``Array`` of just results when they're available, or errback on the first array. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`getXMLHttpRequest()`: Return an ``XMLHttpRequest`` compliant object for the current platform. In order of preference: - ``new XMLHttpRequest()`` - ``new ActiveXObject('Msxml2.XMLHTTP')`` - ``new ActiveXObject('Microsoft.XMLHTTP')`` - ``new ActiveXObject('Msxml2.XMLHTTP.4.0')`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`maybeDeferred(func[, argument...])`: Call a ``func`` with the given arguments and ensure the result is a :mochiref:`Deferred`. ``func``: The function to call. *returns*: A new :mochiref:`Deferred` based on the call to ``func``. If ``func`` does not naturally return a :mochiref:`Deferred`, its result or error value will be wrapped by one. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`loadJSONDoc(url[, queryArguments...])`: Do a simple ``XMLHttpRequest`` to a URL and get the response as a JSON [4]_ document. ``url``: The URL to GET ``queryArguments``: If this function is called with more than one argument, a ``"?"`` and the result of :mochiref:`MochiKit.Base.queryString` with the rest of the arguments are appended to the URL. For example, this will do a GET request to the URL ``http://example.com?bar=baz``:: loadJSONDoc("http://example.com", {bar: "baz"}); *returns*: :mochiref:`Deferred` that will callback with the evaluated JSON [4]_ response upon successful ``XMLHttpRequest`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`sendXMLHttpRequest(req[, sendContent])`: Set an ``onreadystatechange`` handler on an ``XMLHttpRequest`` object and send it off. Will return a cancellable :mochiref:`Deferred` that will callback on success. Note that only ``200`` (OK), ``201`` (CREATED), ``204`` (NO CONTENT) and ``304`` (NOT MODIFIED) are considered success codes. All other status codes will result in an errback with an ``XMLHttpRequestError``. ``req``: An preconfigured ``XMLHttpRequest`` object (open has been called). ``sendContent``: Optional string or DOM content to send over the ``XMLHttpRequest``. *returns*: :mochiref:`Deferred` that will callback with the ``XMLHttpRequest`` instance on success. *Availability*: Available in MochiKit 1.3.1+. Support for 201 and 204 were added in MochiKit 1.4. :mochidef:`succeed([result])`: Return a :mochiref:`Deferred` that has already had ``.callback(result)`` called. This is useful when you're writing synchronous code to an asynchronous interface: i.e., some code is calling you expecting a :mochiref:`Deferred` result, but you don't actually need to do anything asynchronous. Just return ``succeed(theResult)``. See ``fail`` for a version of this function that uses a failing :mochiref:`Deferred` rather than a successful one. ``result``: The result to give to :mochiref:`Deferred.prototype.callback(result)` *returns*: a ``new`` :mochiref:`Deferred` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`wait(seconds[, res])`: Return a new cancellable :mochiref:`Deferred` that will ``.callback(res)`` after at least ``seconds`` seconds have elapsed. *Availability*: Available in MochiKit 1.3.1+ See Also ======== .. [1] AJAX, Asynchronous JavaScript and XML: http://en.wikipedia.org/wiki/AJAX .. [2] Twisted, an event-driven networking framework written in Python: http://twistedmatrix.com/ .. [3] Twisted Deferred Reference: http://twistedmatrix.com/projects/core/documentation/howto/defer.html .. [4] JSON, JavaScript Object Notation: http://json.org/ Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Signal.rst0000660000175000017500000003664111102215564017337 0ustar scottscott.. title:: MochiKit.Signal - Simple universal event handling .. |---| unicode:: U+2014 .. em dash, trimming surrounding whitespace :trim: Name ==== MochiKit.Signal - Simple universal event handling Synopsis ======== Signal for DOM events:: // DOM events are also signals. Connect freely! The functions will be // called with the custom event as a parameter. // calls myClicked.apply(getElement('myID'), [event]) connect('myID', 'onclick', myClicked); // calls wasClicked.apply(myObject, [event]) connect('myID', 'onclick', myObject, wasClicked); // calls myObject.wasClicked(event) connect('myID', 'onclick', myObject, 'wasClicked'); // the event is normalized, no more e = e || window.event! myObject.wasClicked = function(e) { var crossBrowserCoordinates = e.mouse().page; // e.mouse().page is a MochiKit.Style.Coordinates object } Signal for non-DOM events:: // otherObject.gotFlash() will be called when 'flash' signalled. connect(myObject, 'flash', otherObject, 'gotFlash'); // gotBang.apply(otherObject, [...]) will be called when 'bang' signalled. // You can access otherObject from within gotBang as 'this'. connect(myObject, 'bang', otherObject, gotBang); // myFunc.apply(myObject, [...]) will be called when 'flash' signalled. // You can access myObject from within myFunc as 'this'. var ident = connect(myObject, 'flash', myFunc); // You may disconnect with the return value from connect disconnect(ident); // Signal can take parameters. These will be passed along to the // connected functions. signal(myObject, 'flash'); signal(myObject, 'bang', 'BANG!'); Description =========== Event handling was never so easy! This module takes care of all the hard work |---| figuring out which event model to use, trying to retrieve the event object, and handling your own internal events, as well as cleanup when the page is unloaded to clean up IE's nasty memory leakage. This event system is largely based on Qt's signal/slot system. Read more on how that is handled and also how it is used in model/view programming at: http://doc.trolltech.com/ Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.DOM` Overview ======== Using Signal for DOM Events --------------------------- When using MochiKit.Signal, do not use the browser's native event API. That means, no ``onclick="blah"``, no ``elem.addEventListener(...)``, and certainly no ``elem.attachEvent(...)``. This also means that :mochiref:`MochiKit.DOM.addToCallStack` and :mochiref:`MochiKit.DOM.addLoadEvent` should not be used in combination with this module. Signals for DOM objects are named with the ``'on'`` prefix, e.g.: ``'onclick'``, ``'onkeyup'``, etc. When the signal fires, your slot will be called with one parameter, the custom event object. Custom Event Objects for DOM events ----------------------------------- Signals triggered by DOM events are called with a custom event object as a parameter. The custom event object presents a consistent view of the event across all supported platforms and browsers, and provides many conveniences not available even in a correct W3C implementation. See the `DOM Custom Event Object Reference`_ for a detailed API description of this object. If you find that you're accessing the native event for any reason, create a `new ticket`_ and we'll look into normalizing the behavior you're looking for. .. _`new ticket`: http://trac.mochikit.com/newticket .. _`Safari bug 6595`: http://bugs.webkit.org/show_bug.cgi?id=6595 .. _`Safari bug 7790`: http://bugs.webkit.org/show_bug.cgi?id=7790 .. _`Safari bug 8707`: http://bugs.webkit.org/show_bug.cgi?id=8707 .. _`stopPropagation()`: http://developer.mozilla.org/en/docs/DOM:event.stopPropagation .. _`preventDefault()`: http://developer.mozilla.org/en/docs/DOM:event.preventDefault Memory Usage ------------ Any object that has connected slots (via :mochiref:`connect()`) is referenced by the Signal mechanism until it is disconnected via :mochiref:`disconnect()` or :mochiref:`disconnectAll()`. Signal does not leak. It registers an ``'onunload'`` event that disconnects all objects on the page when the browser leaves the page. However, memory usage will grow during the page view for every connection made until it is disconnected. Even if the DOM object is removed from the document, it will still be referenced by Signal until it is explicitly disconnected. In order to conserve memory during the page view, :mochiref:`disconnectAll()` any DOM elements that are about to be removed from the document. Synthesized Events ------------------ Certain events supported by MochiKit are not generated natively by all browsers. MochiKit can synthesize these events even for non-supporting browsers, however, by watching for related events and triggering the appropriate signals at the right times. These events include: ``onmouseenter`` Similar to ``'onmouseover'``, but does not "bubble" up to parent nodes. Such bubbling is often a cause of confusion. On an ``'onmouseenter'`` event, you can be certain that the mouse has left the node attached to the event. *Availability:* Available in MochiKit 1.4+ ``onmouseleave`` Similar to ``'onmouseout'``, but does not "bubble" up to parent nodes. This is the analog to ``'onmouseenter'``. *Availability:* Available in MochiKit 1.4+ ``onmousewheel`` Not strictly synthesized, but named ``'DOMMouseScroll'`` in Gecko-based browsers. MochiKit translates ``'onmousewheel'`` to the corresponding event in these browsers. *Availability:* Available in MochiKit 1.4+ Using Signal for non-DOM objects -------------------------------- Signals are triggered with the :mochiref:`signal(src, 'signal', ...)` function. Additional parameters passed to this are passed onto the connected slots. Explicit signals are not required for DOM events. Slots that are connected to a signal are called in the following manner when that signal is signalled: - If the slot was a single function, then it is called with ``this`` set to the object originating the signal with whatever parameters it was signalled with. - If the slot was an object and a function, then it is called with ``this`` set to the object, and with whatever parameters it was signalled with. - If the slot was an object and a string, then ``object[string]`` is called with the parameters to the signal. API Reference ============= Signal API Reference -------------------- :mochidef:`connect(src, signal, dest[, func])`: Connects a signal to a slot, and return a unique identifier that can be used to disconnect that signal. ``src`` is the object that has the signal. You may pass in a string, in which case, it is interpreted as an id for an HTML element. ``signal`` is a string that represents a signal name. If 'src' is an HTML Element, ``window``, or the ``document``, then it can be one of the 'on-XYZ' events. You must include the 'on' prefix, and it must be all lower-case. ``dest`` and ``func`` describe the slot, or the action to take when the signal is triggered. - If ``dest`` is an object and ``func`` is a string, then ``dest[func].apply(dest, [...])`` will be called when the signal is signalled. - If ``dest`` is an object and ``func`` is a function, then ``func.apply(dest, [...])`` will be called when the signal is signalled. - If ``func`` is undefined and ``dest`` is a function, then ``dest.apply(src, [...])`` will be called when the signal is signalled. No other combinations are allowed and will raise an exception. The return value can be passed to :mochiref:`disconnect` to disconnect the signal. In MochiKit 1.4+, if ``src`` is an object that has a ``__connect__`` method, then ``src.__connect__(ident, signal, objOrFunc, funcOrStr)`` will be called. The ``__connect__`` method is allowed to disconnect the signal. DOM objects can not implement this feature. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`disconnect(ident)`: To disconnect a signal, pass its ident returned by :mochiref:`connect()`. This is similar to how the browser's ``setTimeout`` and ``clearTimeout`` works. In MochiKit 1.4+, if the signal source is an object that has a ``__disconnect__`` method, then ``src.__disconnect__(ident, signal, objOrFunc, funcOrStr)`` will be called. DOM objects can not implement this feature. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`disconnectAll(src[, signal, ...])`: Removes a set of signals from ``src``, similar to calling :mochiref:`disconnect(ident)` for each one. ``disconnectAll(src)`` removes all signals from src. ``disconnectAll(src, 'onmousedown', 'mySignal')`` will remove all ``'onmousedown'`` and ``'mySignal'`` signals from src. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`disconnectAllTo(dest[, func])`: Removes a set of signals connected to ``dest``, similar to calling :mochiref:`disconnect(ident)` for each one. ``disconnectAllTo(dest)`` removes all signals connected to dest. ``disconnectAllTo(dest, func)`` will remove all signals connected to dest using func. *Availability*: Available in MochiKit 1.4+ :mochidef:`signal(src, signal, ...)`: This will signal a signal, passing whatever additional parameters on to the connected slots. ``src`` and ``signal`` are the same as for :mochiref:`connect()`. *Availability*: Available in MochiKit 1.3.1+ DOM Custom Event Object Reference --------------------------------- :mochidef:`event()`: The native event produced by the browser. You should not need to use this. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`src()`: The element that this signal is connected to. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`type()`: The event type (``'click'``, ``'mouseover'``, ``'keypress'``, etc.) as a string. Does not include the ``'on'`` prefix. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`target()`: The element that triggered the event. This may be a child of :mochiref:`src()`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`modifier()`: Returns ``{shift, ctrl, meta, alt, any}``, where each property is ``true`` if its respective modifier key was pressed, ``false`` otherwise. ``any`` is ``true`` if any modifier is pressed, ``false`` otherwise. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`stopPropagation()`: Works like W3C's `stopPropagation()`_. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`preventDefault()`: Works like W3C's `preventDefault()`_. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`stop()`: Shortcut that calls ``stopPropagation()`` and ``preventDefault()``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`key()`: Returns ``{code, string}``. Use ``'onkeydown'`` and ``'onkeyup'`` handlers to detect control characters such as ``'KEY_F1'``. Use the ``'onkeypress'`` handler to detect "printable" characters, such as ``'é'``. When a user presses F1, in ``'onkeydown'`` and ``'onkeyup'`` this method returns ``{code: 122, string: 'KEY_F1'}``. In ``'onkeypress'``, it returns ``{code: 0, string: ''}``. If a user presses Shift+2 on a US keyboard, this method returns ``{code: 50, string: 'KEY_2'}`` in ``'onkeydown'`` and ``'onkeyup'``. In ``'onkeypress'``, it returns ``{code: 64, string: '@'}``. See ``_specialKeys`` in the source code for a comprehensive list of control characters. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`mouse()`: Properties for ``'onmouse*'``, ``'onclick'``, ``'ondblclick'``, and ``'oncontextmenu'``: - ``page`` is a :mochiref:`MochiKit.Style.Coordinates` object that represents the cursor position relative to the HTML document. Equivalent to ``pageX`` and ``pageY`` in Safari, Mozilla, and Opera. - ``client`` is a :mochiref:`MochiKit.Style.Coordinates` object that represents the cursor position relative to the visible portion of the HTML document. Equivalent to ``clientX`` and ``clientY`` on all browsers. Current versions of Safari incorrectly return clientX as relative to the canvas instead of relative to the viewport (`Safari Bug 8707`_). Properties for ``'onmouseup'``, ``'onmousedown'``, ``'onclick'``, and ``'ondblclick'``: - ``mouse().button`` returns ``{left, right, middle}`` where each property is ``true`` if the mouse button was pressed, ``false`` otherwise. Properties for ``'onmousewheel'``: - ``mouse().wheel`` is a :mochiref:`MochiKit.Style.Coordinates` object containing the scroll wheel offset. The number will be positive when scrolling down (or to the right) and negative when scrolling up (or to the left). Note that only Safari 3 currently supports horizontal scrolling. In other browsers, the ``'y'`` component will contain the scroll offset for both directions. Known browser bugs: - Current versions of Safari won't signal ``'ondblclick'`` when attached via ``connect()`` (`Safari Bug 7790`_). - In Safari < 2.0.4, calling ``preventDefault()`` or ``stop()`` in ``'onclick'`` events signalled from ```` tags does not prevent the browser from following those links. - Mac browsers don't report right-click consistently. Firefox signals the slot and sets ``modifier().ctrl`` to true, Opera signals the slot and sets ``modifier().meta`` to ``true``, and Safari doesn't signal the slot at all (`Safari Bug 6595`_). To find a right-click in Safari, Firefox, and IE, you can connect an element to ``'oncontextmenu'``. This doesn't work in Opera. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`relatedTarget()`: Returns the document element that the mouse has moved to. This is generated for ``'onmouseover'`` and ``'onmouseout'`` events. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`confirmUnload(msg)`: In browsers that support the ``'onbeforeunload'`` event (IE and Firefox), calling this in the event handler will show a dialog box that allows the user to confirm or cancel the navigation away from the page. *Availability*: Available in MochiKit 1.4+ Authors ======= - Jonathan Gardner - Beau Hartshorne - Bob Ippolito Copyright ========= Copyright 2006 Jonathan Gardner , Beau Hartshorne , and Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Color.rst0000660000175000017500000004044011102215564017170 0ustar scottscott.. title:: MochiKit.Color - color abstraction with CSS3 support Name ==== MochiKit.Color - color abstraction with CSS3 support Synopsis ======== :: // RGB color expressions are supported assert( objEqual(Color.whiteColor(), Color.fromString("rgb(255,100%, 255)")) ); // So is instantiating directly from HSL or RGB values. // Note that fromRGB and fromHSL take numbers between 0.0 and 1.0! assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) ); // Or even SVG color keyword names, as per CSS3! assert( Color.fromString("aquamarine"), "#7fffd4" ); // NSColor-like colors built in assert( Color.whiteColor().toHexString() == "#ffffff" ); Description =========== MochiKit.Color is an abstraction for handling colors and strings that represent colors. Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.DOM` - :mochiref:`MochiKit.Style` Overview ======== MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with alpha. It supports parsing and generating of CSS3 colors, and has a full CSS3 (SVG) color table. All of the functionality in this module is exposed through a Color constructor and its prototype, but a few of its internals are available for direct use at module level. API Reference ============= Constructors ------------ :mochidef:`Color()`: Represents a color. Component values should be integers between ``0.0`` and ``1.0``. You should use one of the :mochiref:`Color` factory functions such as :mochiref:`Color.fromRGB`, :mochiref:`Color.fromHSL`, etc. instead of constructing :mochiref:`Color` objects directly. :mochiref:`Color` instances can be compared with :mochiref:`MochiKit.Base.compare` (though ordering is on RGB, so is not particularly meaningful except for equality), and the default ``toString`` implementation returns :mochiref:`Color.prototype.toHexString()`. :mochiref:`Color` instances are immutable, and much of the architecture is inspired by AppKit's NSColor [1]_ *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromBackground(elem)`: Returns a :mochiref:`Color` object based on the background of the provided element. Equivalent to:: c = Color.fromComputedStyle( elem, "backgroundColor", "background-color") || Color.whiteColor(); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromComputedStyle(elem, style)`: Returns a :mochiref:`Color` object based on the result of :mochiref:`MochiKit.Style.getStyle(elem, style)` or ``null`` if not found. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromHexString(hexString)`: Returns a :mochiref:`Color` object from the given hexadecimal color string. For example, ``"#FFFFFF"`` would return a :mochiref:`Color` with RGB values ``[255/255, 255/255, 255/255]`` (white). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromHSL(hue, saturation, lightness, alpha=1.0)`: Return a :mochiref:`Color` object from the given ``hue``, ``saturation``, ``lightness`` values. Values should be numbers between ``0.0`` and ``1.0``. If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used. Alternate form: :mochiref:`Color.fromHSL({h: hue, s: saturation, l: lightness, a: alpha})` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromHSLString(hslString)`: Returns a :mochiref:`Color` object from the given decimal hsl color string. For example, ``"hsl(0,0%,100%)"`` would return a :mochiref:`Color` with HSL values ``[0/360, 0/360, 360/360]`` (white). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromHSV(hue, saturation, value, alpha=1.0)`: Return a :mochiref:`Color` object from the given ``hue``, ``saturation``, ``value`` values. Values should be numbers between ``0.0`` and ``1.0``. If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used. Alternate form: :mochiref:`Color.fromHSV({h: hue, s: saturation, v: value, a: alpha})` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromName(colorName)`: Returns a :mochiref:`Color` object corresponding to the given SVG 1.0 color keyword name [2]_ as per the W3C CSS3 Color Module [3]_. ``"transparent"`` is also accepted as a color name, and will return :mochiref:`Color.transparentColor()`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromRGB(red, green, blue, alpha=1.0)`: Return a :mochiref:`Color` object from the given ``red``, ``green``, ``blue``, and ``alpha`` values. Values should be numbers between ``0`` and ``1.0``. If ``alpha`` is not given, then ``1.0`` (completely opaque) will be used. Alternate form: :mochiref:`Color.fromRGB({r: red, g: green, b: blue, a: alpha})` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromRGBString(rgbString)`: Returns a :mochiref:`Color` object from the given decimal rgb color string. For example, ``"rgb(255,255,255)"`` would return a :mochiref:`Color` with RGB values ``[255/255, 255/255, 255/255]`` (white). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromText(elem)`: Returns a :mochiref:`Color` object based on the text color of the provided element. Equivalent to:: c = Color.fromComputedStyle(elem, "color") || Color.whiteColor(); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.fromString(rgbOrHexString)`: Returns a :mochiref:`Color` object from the given RGB, HSL, hex, or name. Will return ``null`` if the string can not be parsed by any of these methods. See :mochiref:`Color.fromHexString`, :mochiref:`Color.fromRGBString`, :mochiref:`Color.fromHSLString` and :mochiref:`Color.fromName` more information. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.namedColors()`: Returns an object with properties for each SVG 1.0 color keyword name [2]_ supported by CSS3 [3]_. Property names are the color keyword name in lowercase, and the value is a string suitable for :mochiref:`Color.fromString()`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.colorWithAlpha(alpha)`: Return a new :mochiref:`Color` based on this color, but with the provided ``alpha`` value. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.colorWithHue(hue)`: Return a new :mochiref:`Color` based on this color, but with the provided ``hue`` value. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.colorWithSaturation(saturation)`: Return a new :mochiref:`Color` based on this color, but with the provided ``saturation`` value (using the HSL color model). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.colorWithLightness(lightness)`: Return a new :mochiref:`Color` based on this color, but with the provided ``lightness`` value. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.darkerColorWithLevel(level)`: Return a new :mochiref:`Color` based on this color, but darker by the given ``level`` (between ``0`` and ``1.0``). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.lighterColorWithLevel(level)`: Return a new :mochiref:`Color` based on this color, but lighter by the given ``level`` (between ``0`` and ``1.0``). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.blendedColor(other, fraction=0.5)`: Return a new :mochiref:`Color` whose RGBA component values are a weighted sum of this color and ``other``. Each component of the returned color is the ``fraction`` of other's value plus ``1 - fraction`` of this color's. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.isLight()`: Return ``true`` if the lightness value of this color is greater than ``0.5``. Note that ``alpha`` is ignored for this calculation (color components are not premultiplied). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.isDark()`: Return ``true`` if the lightness value of this color is less than or equal to ``0.5``. Note that ``alpha`` is ignored for this calculation (color components are not premultiplied). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.toRGBString()`: Return the decimal ``"rgb(red, green, blue)"`` string representation of this color. If the alpha component is not ``1.0`` (fully opaque), the ``"rgba(red, green, blue, alpha)"`` string representation will be used. For example:: assert( Color.whiteColor().toRGBString() == "rgb(255,255,255)" ); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.toHSLString()`: Return the decimal ``"hsl(hue, saturation, lightness)"`` string representation of this color. If the alpha component is not ``1.0`` (fully opaque), the ``"hsla(hue, saturation, lightness, alpha)"`` string representation will be used. For example:: assert( Color.whiteColor().toHSLString() == "hsl(0,0,360)" ); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.toHexString()`: Return the hexadecimal ``"#RRGGBB"`` string representation of this color. Note that the alpha component is completely ignored for hexadecimal string representations! For example:: assert( Color.whiteColor().toHexString() == "#FFFFFF" ); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.asRGB()`: Return the RGB (red, green, blue, alpha) components of this color as an object with ``r``, ``g``, ``b``, and ``a`` properties that have values between ``0.0`` and ``1.0``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.asHSL()`: Return the HSL (hue, saturation, lightness, alpha) components of this color as an object with ``h``, ``s``, ``l`` and ``a`` properties that have values between ``0.0`` and ``1.0``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.prototype.asHSV()`: Return the HSV (hue, saturation, value, alpha) components of this color as an object with ``h``, ``s``, ``v`` and ``a`` properties that have values between ``0.0`` and ``1.0``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.blackColor()`: Return a :mochiref:`Color` object whose RGB values are 0, 0, 0 (#000000). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.blueColor()`: Return a :mochiref:`Color` object whose RGB values are 0, 0, 1 (#0000ff). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.brownColor()`: Return a :mochiref:`Color` object whose RGB values are 0.6, 0.4, 0.2 (#996633). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.cyanColor()`: Return a :mochiref:`Color` object whose RGB values are 0, 1, 1 (#00ffff). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.darkGrayColor()`: Return a :mochiref:`Color` object whose RGB values are 1/3, 1/3, 1/3 (#555555). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.grayColor()`: Return a :mochiref:`Color` object whose RGB values are 0.5, 0.5, 0.5 (#808080). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.greenColor()`: Return a :mochiref:`Color` object whose RGB values are 0, 1, 0. (#00ff00). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.lightGrayColor()`: Return a :mochiref:`Color` object whose RGB values are 2/3, 2/3, 2/3 (#aaaaaa). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.magentaColor()`: Return a :mochiref:`Color` object whose RGB values are 1, 0, 1 (#ff00ff). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.orangeColor()`: Return a :mochiref:`Color` object whose RGB values are 1, 0.5, 0 (#ff8000). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.purpleColor()`: Return a :mochiref:`Color` object whose RGB values are 0.5, 0, 0.5 (#800080). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.redColor()`: Return a :mochiref:`Color` object whose RGB values are 1, 0, 0 (#ff0000). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.whiteColor()`: Return a :mochiref:`Color` object whose RGB values are 1, 1, 1 (#ffffff). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.yellowColor()`: Return a :mochiref:`Color` object whose RGB values are 1, 1, 0 (#ffff00). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Color.transparentColor()`: Return a :mochiref:`Color` object that is completely transparent (has alpha component of 0). *Availability*: Available in MochiKit 1.3.1+ Functions --------- :mochidef:`clampColorComponent(num, scale)`: Returns ``num * scale`` clamped between ``0`` and ``scale``. :mochiref:`clampColorComponent` is not exported by default when using JSAN. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`hslToRGB(hue, saturation, lightness, alpha)`: Computes RGB values from the provided HSL values. The return value is a mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys. Alternate form: :mochiref:`hslToRGB({h: hue, s: saturation, l: lightness, a: alpha})`. :mochiref:`hslToRGB` is not exported by default when using JSAN. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`hsvToRGB(hue, saturation, value, alpha)`: Computes RGB values from the provided HSV values. The return value is a mapping with ``"r"``, ``"g"``, ``"b"`` and ``"a"`` keys. Alternate form: :mochiref:`hsvToRGB({h: hue, s: saturation, v: value, a: alpha})`. :mochiref:`hsvToRGB` is not exported by default when using JSAN. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toColorPart(num)`: Convert num to a zero padded hexadecimal digit for use in a hexadecimal color string. Num should be an integer between ``0`` and ``255``. :mochiref:`toColorPart` is not exported by default when using JSAN. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`rgbToHSL(red, green, blue, alpha)`: Computes HSL values based on the provided RGB values. The return value is a mapping with ``"h"``, ``"s"``, ``"l"`` and ``"a"`` keys. Alternate form: :mochiref:`rgbToHSL({r: red, g: green, b: blue, a: alpha})`. :mochiref:`rgbToHSL` is not exported by default when using JSAN. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`rgbToHSV(red, green, blue, alpha)`: Computes HSV values based on the provided RGB values. The return value is a mapping with ``"h"``, ``"s"``, ``"v"`` and ``"a"`` keys. Alternate form: :mochiref:`rgbToHSV({r: red, g: green, b: blue, a: alpha})`. :mochiref:`rgbToHSV` is not exported by default when using JSAN. *Availability*: Available in MochiKit 1.3.1+ See Also ======== .. [1] Application Kit Reference - NSColor: http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/ObjC_classic/Classes/NSColor.html .. [2] SVG 1.0 color keywords: http://www.w3.org/TR/SVG/types.html#ColorKeywords .. [3] W3C CSS3 Color Module: http://www.w3.org/TR/css3-color/#svg-color Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/DragAndDrop.rst0000660000175000017500000001346111102215564020242 0ustar scottscott.. title:: MochiKit.DragAndDrop - drag and drop elements with MochiKit Name ==== MochiKit.DragAndDrop - drag and drop elements with MochiKit Synopsis ======== :: // Create a draggable new Draggable('mydrag'); // Create a corresponding droppable new Droppable('mydrop', { accept: ['drag-class'], ondrop: function (element) { alert('"' + element.id + '" was dropped on me'); } }); Description =========== MochiKit.DragAndDrop enables you the power of dragging elements through your pages, for richer interfaces. Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.Iter` - :mochiref:`MochiKit.DOM` - :mochiref:`MochiKit.Color` - :mochiref:`MochiKit.Visual` - :mochiref:`MochiKit.Signal` Overview ======== The implementation was adapted from Scriptaculous_. .. _Scriptaculous: http://script.aculo.us API Reference ============= Constructors ------------ :mochidef:`Draggable(element[, options])`: A object that can be drag with the mouse. You have the following options, with corresponding default values: ``handle (false)``: Option for giving the element where starting the drag. By default it's the element itself, but you can either put a class of a subelement or the id of another element as handle. ``starteffect (MochiKit.Visual.Opacity)``: Function called once the drag has begun, taking the dragged element as argument. It's an effect by default but you can define any callback. ``reverteffect (MochiKit.Visual.Move)``: Effect applied when drag is cancelled. You have to define the ``revert`` option to enable the call. By default it brings the element back to its initial position, so you should know what you want when you modify this. The function should return an effect that can be cancelled. ``endeffect (MochiKit.Visual.Opacity)``: Pending part of starteffect. If you have modified your element during start, you'd usually want to revert it in the function. ``zindex (1000)``: Zindex of the drag element. By default it brings it to front. ``revert (false)``: Indicate if the reverteffect function should be called. If you define a function here, this function will be called before reverteffect, with the element as first argument. ``snap (false)``: Define the behaviour of the drag element when moving. It can either be a function, a value or an array of two values. If it's a function, it should take the (x, y) position of the element as arguments, and return the position draw in the browser. If its a value, it's used as a modulo for each coordinates. If it's an array, each value is applied for the corresponding coordinate. ``selectclass (null)``: If defined, name of CSS class applied during the drag. ``ghosting (null)``: Make a ghost from the draggable: clone it at start, then remove the clone at end. ``onchange (MochiKit.Base.noop)``: Function called when updates are made on the draggable object. ``scroll (false)``: Element to scroll around, if precised. For example, ``window`` will allow the draggable to scroll in the page. ``scrollSensitivity (20)``: Scroll sensitivity, used when scroll is used. ``scrollSpeed (15)``: Scroll speed, used when scroll is used. A draggable generates some signals during its lifetime: start, drag and end. They are available through the Draggables handler, and are called with a draggable as argument. You can register a callback for these events like this:: onStart = function (draggable) { // Do some stuff }; connect(Draggables, 'start', onStart); *Availability*: Available in MochiKit 1.4+ :mochidef:`Droppable(element[, options])`: A object where you can drop a draggable. You have the following options, with corresponding default values: ``greedy (true)``: Stop on this droppable when a draggable drops over it. ``hoverclass (null)``: If defined, name of CSS class applied when a draggable is hover the droppable element (hover state). ``hoverfunc (MochiKit.Base.noop)``: Function called on hover state. ``accept (null)``: Array of CSS classes allowed to drop on this. ``activeclass (null)``: If defined, name of CSS class applied if a possible draggable begins its start (active state). ``onactive (MochiKit.Base.noop)``: Function called on active state. ``containment ([])``: Specify a list of elements to check for active state: only the children of the specified elements can be dropped. Mainly useful for Sortable. ``onhover (MochiKit.Base.noop)``: Specific hover function, mainly used for Sortable. ``ondrop (MochiKit.Base.noop)``: Function called when a draggable is dropped. The function takes three arguments: the draggable element, the droppable element, and the event that raised the drop. *Availability*: Available in MochiKit 1.4+ Authors ======= - Thomas Herve - Bob Ippolito - Originally adapted from Script.aculo.us Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php Portions adapted from `Scriptaculous`_ are available under the terms of the `MIT License`_. MochiKit-1.4.2/doc/rst/MochiKit/Sortable.rst0000660000175000017500000001225611102215564017671 0ustar scottscott.. title:: MochiKit.Sortable - sortable with drag and drop lists Name ==== MochiKit.Sortable - sortable with drag and drop lists Synopsis ======== ::
  • mochibot.com
  • pythonmac.org
  • undefined.org
  • python.org
Description =========== MochiKit.Sortable add a new Sortable object to manipulate easily drag&drop in lists. Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.Iter` - :mochiref:`MochiKit.DOM` - :mochiref:`MochiKit.Color` - :mochiref:`MochiKit.Visual` - :mochiref:`MochiKit.Signal` - :mochiref:`MochiKit.DragAndDrop` Overview ======== MochiKit.Sortable mainly contains the Sortable object offering facilities to manipulate a list and drag its items to reorder it. It can also be serialized for being send to server. It is ported from Scriptaculous_. .. _Scriptaculous: http://script.aculo.us API Reference ============= Objects defined --------------- :mochidef:`SortableObserver`: Observer for DragAndDrop object. You normally don't have to access this, only for customization purpose. *Availability*: Available in MochiKit 1.4+ :mochidef:`Sortable.create(element [, options])`: Create a new Sortable. Usually you'll call it with a UL element, but it can be customized with options to use something else. You have the following options: ================= ================== element element tag 'li' dropOnEmpty false overlap 'vertical' constraint 'vertical' containment element handle false only false hoverclass null ghosting false scroll false scrollSensitivity 20 scrollSpeed 15 format /^[^_]*_(.*)$/ onChange MochiKit.Base.noop onUpdate MochiKit.Base.noop tree false treeTag 'ul' ================= ================== ``tag``: Name of the tag used to make the draggable elements. It matches all the childNodes of the Sortable element with this tag. ``only``: Class or array of classes used to filter the children, combined with the tag criteria. ``format``: Regular expression which serves as a match filter for serialization, on children' ids. For example, with the default value, you'll get ['1', '2', '3', '4'] with ids ['sort_1', 'sort_2', 'sort_3', 'sort_4']. ``onChange``: Callback called when an element moves between others in the Sortable. It's called for *each* movements, even if you don't release the mouse. ``onUpdate``: Callback called when the order changes in the Sortable. It's called only if the Sortable is modified, after you dropped an element. ``tree``: Option for creating a Sortable tree. It's an experimental setting, that can be very slow even with a few elements. You can customize its behaviour with the ``treeTag`` option, that defines the node used to make branches in your tree (that contains leaves). Other options are passed to the Draggables and Droppables objects created. Refer to :mochiref:`MochiKit.DragAndDrop` for more information. A bug with Internet Explorer rendering engine can cause a problem with the default effect used on start (the symptom being that the rows vanish). If you encounter this problem, pass :mochiref:`MochiKit.Base.noop` as the ``starteffect`` option. *Availability*: Available in MochiKit 1.4+ :mochidef:`Sortable.destroy(element)`: Destroy a previously created sortable. It prevents further use of the Sortable functionnality on the element, unless recreated. *Availability*: Available in MochiKit 1.4+ :mochidef:`Sortable.serialize(element [, options])`: Serialize the content of a Sortable. Useful to send this content through a XMLHTTPRequest. The options overrides the ones of the Sortable only for the serialization. ====== ========================================== tag tag from the Sortable only only from the Sortable name id of the element format format of the Sortable or /^[^_]*_(.*)$ ====== ========================================== *Availability*: Available in MochiKit 1.4+ Authors ======= - Thomas Herve - Bob Ippolito - Originally adapted from Script.aculo.us Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php Portions adapted from `Scriptaculous`_ are available under the terms of the `MIT License`_. .. _`Apache License, Version 2.0`: http://www.apache.org/licenses/LICENSE-2.0.html MochiKit-1.4.2/doc/rst/MochiKit/DateTime.rst0000660000175000017500000000556711102215564017621 0ustar scottscott.. title:: MochiKit.DateTime - "what time is it anyway?" Name ==== MochiKit.DateTime - "what time is it anyway?" Synopsis ======== :: stringDate = toISOTimestamp(new Date()); dateObject = isoTimestamp(stringDate); Description =========== Remote servers don't give you JavaScript Date objects, and they certainly don't want them from you, so you need to deal with string representations of dates and timestamps. MochiKit.Date does that. Dependencies ============ None. API Reference ============= Functions --------- :mochidef:`isoDate(str)`: Convert an ISO 8601 date (YYYY-MM-DD) to a ``Date`` object. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`isoTimestamp(str)`: Convert any ISO 8601 [1]_ timestamp (or something reasonably close to it) to a ``Date`` object. Will accept the "de facto" form: YYYY-MM-DD hh:mm:ss or (the proper form): YYYY-MM-DDThh:mm:ssZ If a time zone designator ("Z" or "[+-]HH:MM") is not present, then the local timezone is used. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toISOTime(date)`: Convert a ``Date`` object to a string in the form of hh:mm:ss *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toISOTimestamp(date, realISO=false)`: Convert a ``Date`` object to something that's ALMOST but not quite an ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it would be: YYYY-MM-DDThh:mm:ssZ However, we see junk in SQL and other places that looks like this: YYYY-MM-DD hh:mm:ss So, this function returns the latter form, despite its name, unless you pass ``true`` for ``realISO``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toISODate(date)`: Convert a ``Date`` object to an ISO 8601 [1]_ date string (YYYY-MM-DD) *Availability*: Available in MochiKit 1.3.1+ :mochidef:`americanDate(str)`: Converts a MM/DD/YYYY date to a ``Date`` object *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toPaddedAmericanDate(date)`: Converts a ``Date`` object to an MM/DD/YYYY date, e.g. 01/01/2001 *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toAmericanDate(date)`: Converts a ``Date`` object to an M/D/YYYY date, e.g. 1/1/2001 *Availability*: Available in MochiKit 1.3.1+ See Also ======== .. [1] W3C profile of ISO 8601: http://www.w3.org/TR/NOTE-datetime Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Base.rst0000660000175000017500000013665411102215564017001 0ustar scottscott.. title:: MochiKit.Base - functional programming and useful comparisons Name ==== MochiKit.Base - functional programming and useful comparisons Synopsis ======== :: myObjectRepr = function () { // gives a nice, stable string representation for objects, // ignoring any methods var keyValuePairs = []; for (var k in this) { var v = this[k]; if (typeof(v) != 'function') { keyValuePairs.push([k, v]); } }; keyValuePairs.sort(compare); return "{" + map( function (pair) { return map(repr, pair).join(":"); }, keyValuePairs ).join(", ") + "}"; }; // repr() will look for objects that have a repr method myObjectArray = [ {"a": 3, "b": 2, "repr": myObjectRepr}, {"a": 1, "b": 2, "repr": myObjectRepr} ]; // sort it by the "a" property, check to see if it matches myObjectArray.sort(keyComparator("a")); expectedRepr = '[{"a": 1, "b": 2}, {"a": 3, "b": 2}]'; assert( repr(myObjectArray) == expectedRepr ); // get just the "a" values out into an array sortedAValues = map(itemgetter("a"), myObjectArray); assert( compare(sortedAValues, [1, 3]) == 0 ); // serialize an array as JSON, unserialize it, expect something equivalent myArray = [1, 2, "3", null, undefined]; assert( objEqual(evalJSON(serializeJSON(myArray)), myArray) ); Description =========== :mochiref:`MochiKit.Base` is the foundation for the MochiKit suite. It provides: - An extensible comparison facility (:mochiref:`compare`, :mochiref:`registerComparator`) - An extensible programmer representation facility (:mochiref:`repr`, :mochiref:`registerRepr`) - An extensible JSON [1]_ serialization and evaluation facility (:mochiref:`serializeJSON`, :mochiref:`evalJSON`, :mochiref:`registerJSON`) - A simple adaptation facility (:mochiref:`AdapterRegistry`) - Convenience functions for manipulating objects and Arrays (:mochiref:`update`, :mochiref:`setdefault`, :mochiref:`extend`, etc.) - Array-based functional programming (:mochiref:`map`, :mochiref:`filter`, etc.) - Bound and partially applied functions (:mochiref:`bind`, :mochiref:`method`, :mochiref:`partial`) Python users will feel at home with :mochiref:`MochiKit.Base`, as the facilities are quite similar to those available as part of Python and the Python standard library. Dependencies ============ None. Overview ======== Comparison ---------- The comparators (operators for comparison) in JavaScript are deeply broken, and it is not possible to teach them new tricks. MochiKit exposes an extensible comparison facility as a simple :mochiref:`compare(a, b)` function, which should be used in lieu of JavaScript's operators whenever comparing objects other than numbers or strings (though you can certainly use :mochiref:`compare` for those, too!). The :mochiref:`compare` function has the same signature and return value as a sort function for ``Array.prototype.sort``, and is often used in that context. Defining new comparators for the :mochiref:`compare` function to use is done by adding an entry to its :mochiref:`AdapterRegistry` with the :mochiref:`registerComparator` function. Programmer Representation ------------------------- JavaScript's default representation mechanism, ``toString``, is notorious for having terrible default behavior. It's also very unwise to change that default, as other JavaScript code you may be using may depend on it. It's also useful to separate the concept of a "string representation" and a "string representation for programmers", much like Python does with its str and repr protocols. :mochiref:`repr` provides this programmer representation for JavaScript, in a way that doesn't require object prototype hacking: using an :mochiref:`AdapterRegistry`. Objects that implement the repr protocol can either implement a ``.repr()`` or ``.__repr__()`` method, or they can simply have an adapter setup to generate programmer representations. By default, the registry provides nice representations for ``null``, ``undefined``, ``Array``, and objects or functions with a ``NAME`` attribute that use the default ``toString``. For objects that ``repr`` doesn't already understand, it simply defaults to ``toString``, so it will integrate seamlessly with code that implements the idiomatic JavaScript ``toString`` method! To define a programmer representation for your own objects, simply add a ``.repr()`` or ``.__repr__()`` method that returns a string. For objects that you didn't create (e.g., from a script you didn't write, or a built-in object), it is instead recommended that you create an adapter with :mochiref:`registerRepr`. JSON Serialization ------------------ JSON [1]_, JavaScript Object Notation, is a widely used serialization format in the context of web development. It's extremely simple, lightweight, and fast. In its essence, JSON is a restricted subset of JavaScript syntax suitable for sending over the wire that can be unserialized with a simple eval. It's often used as an alternative to XML in "AJAX" contexts because it is compact, fast, and much simpler to use for most purposes. To create a JSON serialization of any object, simply call :mochiref:`serializeJSON()` with that object. To unserialize a JSON string, simply call :mochiref:`evalJSON()` with the serialization. In order of precedence, :mochiref:`serializeJSON` coerces the given argument into a JSON serialization: 1. Primitive types are returned as their JSON representation: ``string``, ``number``, ``boolean``, ``null``. 2. If the object has a ``__json__`` or ``json`` method, then it is called with no arguments. If the result of this method is not the object itself, then the new object goes through rule processing again (e.g. it may return a string, which is then serialized in JSON format). 3. If the object is ``Array``-like (has a ``length`` property that is a number, and is not a function), then it is serialized as a JSON array. Each element will be processed according to these rules in order. Elements that can not be serialized (e.g. functions) will be replaced with ``undefined``. 4. The ``jsonRegistry`` :mochiref:`AdapterRegistry` is consulted for an adapter for this object. JSON adapters take one argument (the object), and are expected to behave like a ``__json__`` or ``json`` method (return another object to be serialized, or itself). 5. If the object is ``undefined``, a ``TypeError`` is thrown. If you wish to serialize ``undefined`` as ``null`` or some other value, you should create an adapter to do so. 6. If no adapter is available, the object is enumerated and serialized as a JSON object (name:value pairs). All names are expected to be strings. Each value is serialized according to these rules, and if it can not be serialized (e.g. methods), then that name:value pair will be skipped. Adapter Registries ------------------ MochiKit makes extensive use of adapter registries, which enable you to implement object-specific behaviors for objects that you do not necessarily want to modify, such as built-in objects. This is especially useful because JavaScript does not provide a method for hiding user-defined properties from ``for propName in obj`` enumeration. :mochiref:`AdapterRegistry` is simply an encapsulation for an ordered list of "check" and "wrap" function pairs. Each :mochiref:`AdapterRegistry` instance should perform one function, but may have multiple ways to achieve that function based upon the arguments. One way to think of it is as a poor man's generic function, or multiple dispatch (on arbitrary functions, not just type!). Check functions take one or more arguments, and return ``true`` if the argument list is suitable for the wrap function. Check functions should perform "cheap" checks of an object's type or contents, before the "expensive" wrap function is called. Wrap functions take the same arguments as check functions and do some operation, such as creating a programmer representation or comparing both arguments. Convenience Functions --------------------- Much of :mochiref:`MochiKit.Base` is there to simply remove the grunt work of doing generic JavaScript programming. Need to take every property from one object and set them on another? No problem, just call :mochiref:`update(dest, src)`! What if you just wanted to update keys that weren't already set? Look no further than :mochiref:`setdefault(dest, src[, ...])`. Want to return a mutable object, but don't want to suffer the consequences if the user mutates it? Just :mochiref:`clone(it)` and you'll get a copy-on-write clone. Cheaper than a copy! Need to extend an ``Array`` with another array? Or even an ``Array``-like object such as a ``NodeList`` or the special ``arguments`` object? Even if you need to skip the first few elements of the source ``Array``-like object, it's no problem with :mochiref:`extend(dstArray, srcArrayLike[, skip])`! Wouldn't it be convenient to have all of the JavaScript operators were available as functions somewhere? That's what the :mochiref:`operators` table is for, and it even comes with additional operators based on the :mochiref:`compare` function. Need to walk some tree of objects and manipulate or find something in it? A DOM element tree perhaps? Use :mochiref:`nodeWalk(node, visitor)`! There's plenty more, so check out the `API Reference`_ below. Functional Programming ---------------------- Functional programming constructs such as :mochiref:`map` and :mochiref:`filter` can save you a lot of time, because JavaScript iteration is error-prone and arduous. Writing less code is the best way to prevent bugs, and functional programming can help you do that. :mochiref:`MochiKit.Base` ships with a few simple Array-based functional programming constructs, namely :mochiref:`map` and :mochiref:`filter`, and their "extended" brethren, :mochiref:`xmap` and :mochiref:`xfilter`. :mochiref:`map(func, arrayLike[, ...])` takes a function and an ``Array``-like object, and creates a new ``Array``. The new ``Array`` is the result of ``func(element)`` for every element of ``arrayLike``, much like the ``Array.prototype.map`` extension in Mozilla. However, :mochiref:`MochiKit.Base` takes that a step further and gives you the full blown Python version of :mochiref:`map`, which will take several ``Array``-like objects, and calls the function with one argument per given ``Array``-like, e.g.:: var arrayOne = [1, 2, 3, 4, 5]; var arrayTwo = [1, 5, 2, 4, 3]; var arrayThree = [5, 2, 1, 3, 4]; var biggestElements = map(objMax, arrayOne, arrayTwo, arrayThree); assert( objEqual(biggestElements, [5, 5, 3, 4, 5]) ); :mochiref:`filter(func, arrayLike[, self])` takes a function and an ``Array``-like object, and returns a new ``Array``. This is basically identical to the ``Array.prototype.filter`` extension in Mozilla. self, if given, will be used as ``this`` in the context of func when called. :mochiref:`xmap` and :mochiref:`xfilter` are just special forms of :mochiref:`map` and :mochiref:`filter` that accept a function as the first argument, and use the extra arguments as the ``Array``-like. Not terribly interesting, but a definite time-saver in some cases. If you appreciate the functional programming facilities here, you should definitely check out :mochiref:`MochiKit.Iter`, which provides full blown iterators, :mochiref:`MochiKit.Iter.range`, :mochiref:`MochiKit.Iter.reduce`, and a near-complete port of Python's itertools [2]_ module, with some extra stuff thrown in for good measure! Bound and Partial Functions --------------------------- JavaScript's method-calling special form and lack of bound functions (functions that know what ``this`` should be) are one of the first stumbling blocks that programmers new to JavaScript face. The :mochiref:`bind(func, self)` method fixes that right up by returning a new function that calls func with the right ``this``. In order to take real advantage of all this fancy functional programming stuff, you're probably going to want partial application. This allows you to create a new function from an existing function that remembers some of the arguments. For example, if you wanted to compare a given object to a slew of other objects, you could do something like this:: compareWithOne = partial(compare, 1); results = map(compareWithOne, [0, 1, 2, 3]); assert( objEqual(results, [-1, 0, 1, 1]) ); One of the better uses of partial functions is in :mochiref:`MochiKit.DOM`, which is certainly a must-see for those of you creating lots of DOM elements with JavaScript! API Reference ============= Errors ------ :mochidef:`NotFound`: A singleton error raised when no suitable adapter is found *Availability*: Available in MochiKit 1.3.1+ Constructors ------------ :mochidef:`AdapterRegistry`: A registry to facilitate adaptation. All ``check``/``wrap`` function pairs in a given registry should take the same number of arguments. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`AdapterRegistry.prototype.register(name, check, wrap[, override])`: ``name``: a unique identifier used to identify this adapter so that it may be unregistered. ``check``: function that should return ``true`` if the given arguments are appropriate for the ``wrap`` function. ``wrap``: function that takes the same parameters as ``check`` and does the adaptation. Every ``wrap``/``check`` function pair in the registry should have the same number of arguments. ``override``: if ``true``, the ``check`` function will be given highest priority. Otherwise, the lowest. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`AdapterRegistry.prototype.match(obj[, ...])`: Find an adapter for the given arguments by calling every ``check`` function until one returns ``true``. If no suitable adapter is found, throws :mochiref:`NotFound`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`AdapterRegistry.prototype.unregister(name)`: Remove a named adapter from the registry *Availability*: Available in MochiKit 1.3.1+ :mochidef:`NamedError`: Convenience constructor for creating new errors (e.g. :mochiref:`NotFound`) *Availability*: Available in MochiKit 1.3.1+ Functions --------- :mochidef:`arrayEqual(self, arr)`: Compare the arrays ``self`` and ``arr`` for equality using ``compare`` on each element. Uses a fast-path for length differences. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`average(lst[, ...])`: This function is an alias of :mochiref:`mean()`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`bind(func, self[, arg, ...])`: Return a copy of ``func`` bound to ``self``. This means whenever and however the returned function is called, ``this`` will always reference the given ``self``. ``func`` may be either a function object, or a string. If it is a string, then ``self[func]`` will be used, making these two statements equivalent:: bind("method", self); bind(self.method, self); Calling :mochiref:`bind(func, self)` on an already bound function will return a new function that is bound to the new ``self``! If ``self`` is ``undefined``, then the previous ``self`` is used. If ``self`` is ``null``, then the ``this`` object is used (which may or may not be the global object). To force binding to the global object, you should pass it explicitly. Additional arguments, if given, will be partially applied to the function. These three expressions are equivalent and return equally efficient functions (:mochiref:`bind` and :mochiref:`partial` share the same code path): - :mochiref:`bind(oldfunc, self, arg1, arg2)` - :mochiref:`bind(partial(oldfunc, arg1, arg2), self)` - :mochiref:`partial(bind(oldfunc, self), arg1, arg2)` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`bindLate(func, self[, arg, ...])`: Alternate version of :mochiref:`bind` that uses late lookup of the ``func`` parameter in ``self``. I.e, the ``self[func]`` function lookup will occur on each call to the returned function, not when ``bindLate`` is called. Note that this difference is only applicable when ``func`` is a string, otherwise ``bindLate`` and ``bind`` are identical. *Availability*: Available in MochiKit 1.4+ :mochidef:`bindMethods(self)`: Replace all functions ``meth`` on ``self`` with :mochiref:`bind(meth, self)`. This emulates Python's bound instance methods, where there is no need to worry about preserving ``this`` when the method is used as a callback. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`camelize(str)`: Converts hyphenated strings to camelCase:: assert( camelize("border-left") == "borderLeft" ); *Availability*: Available in MochiKit 1.4+ :mochidef:`clone(obj)`: Return a new object using ``obj`` as its prototype. Use this if you want to return a mutable object (e.g. instance state), but don't want the user to mutate it. If they do, it won't have any effect on the original ``obj``. Note that this is a shallow clone, so mutable properties will have to be cloned separately if you want to "protect" them. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`compare(a, b)`: Compare two objects in a sensible manner. Currently this is: 1. ``undefined`` and ``null`` compare equal to each other 2. ``undefined`` and ``null`` are less than anything else 3. If JavaScript says ``a == b``, then we trust it 4. comparators registered with registerComparator are used to find a good comparator. Built-in comparators are currently available for ``Array``-like and ``Date``-like objects. 5. Otherwise hope that the built-in comparison operators do something useful, which should work for numbers and strings. 6. If neither ``a < b`` or ``a > b``, then throw a ``TypeError`` Returns what one would expect from a comparison function: +-----------+---------------+ | Value | Condition | +-----------+---------------+ | ``0`` | ``a == b`` | +-----------+---------------+ | ``1`` | ``a > b`` | +-----------+---------------+ | ``-1`` | ``a < b`` | +-----------+---------------+ *Availability*: Available in MochiKit 1.3.1+ :mochidef:`compose(f1, f2, ..., fN)`: Return a new function as the combination of the given function arguments, equivalent to ``f1(f2(arguments))``. *Availability*: Available in MochiKit 1.4+ :mochidef:`concat(lst[, ...])`: Concatenates all given ``Array``-like arguments and returns a new ``Array``:: var lst = concat(["1","3","5"], ["2","4","6"]); assert( lst.toString() == "1,3,5,2,4,6" ); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`counter(n=1)`: Returns a function that will return a number one greater than the previous returned value, starting at ``n``. For example:: nextId = counter() assert( nextId() == 1 ) assert( nextId() == 2 ) For an iterator with this behavior, see :mochiref:`MochiKit.Iter.count`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`extend(self, obj, skip=0)`: Mutate the array ``self`` by extending it with an ``Array``-like ``obj``, starting from index ``skip``. If ``null`` is given as the initial array, a new one will be created. This mutates *and returns* ``self``, be warned. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`evalJSON(aJSONString)`: Unserialize a JSON [1]_ represenation of an object. Note that this uses the ``eval`` function of the interpreter, and therefore trusts the contents of ``aJSONString`` to be safe. This is acceptable when the JSON and JavaScript application originate from the same server, but in other scenarios it may not be the appropriate security model. Currently, a validating JSON parser is beyond the scope of MochiKit, but there is one available from json.org [1]_. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`filter(fn, lst)`: Returns a new ``Array`` composed of all elements from ``lst`` where ``fn(lst[i])`` returns a true value. If ``fn`` is ``null``, ``operator.truth`` will be used. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`findValue(lst, value, start=0, end=lst.length)`: Finds the index of ``value`` in the ``Array``-like object ``lst`` using :mochiref:`compare`. The search starts at the index ``start``, and ends at the index ``end - 1``. If ``value`` is not found in ``lst``, it will return ``-1``. For example:: assert( findValue([1, 2, 3, 2, 1], 2) == 1 ) assert( findValue([1, 2, 3, 2, 1], 2, 2) == 3 ) *Availability*: Available in MochiKit 1.3.1+ :mochidef:`findIdentical(lst, value, start=0, end=lst.length)`: Finds the index of ``value`` in the ``Array``-like object ``lst`` using the ``===`` operator. The search starts at the index ``start``, and ends at the index ``end - 1``. If ``value`` is not found in ``lst``, it will return ``-1``. You should use this function instead of :mochiref:`findValue` if ``lst`` may be comprised of objects for which no comparator is defined and all you care about is finding an identical object (e.g. the same instance), or if ``lst`` is comprised of just numbers or strings and performance is important. For example:: assert( findIdentical([1, 2, 3, 2, 1], 2) == 1 ) assert( findIdentical([1, 2, 3, 2, 1], 2, 2) == 3 ) *Availability*: Available in MochiKit 1.3.1+ :mochidef:`flattenArguments(arg[, ...])`: Given a bunch of arguments, return a single ``Array`` containing all of those arguments. Any ``Array``-like argument will be extended in-place, e.g.:: compare(flattenArguments(1, [2, 3, [4, 5]]), [1, 2, 3, 4, 5]) == 0 *Availability*: Available in MochiKit 1.3.1+ :mochidef:`flattenArray(lst)`: Return a new ``Array`` consisting of every item in lst with ``Array`` items expanded in-place recursively. This differs from :mochiref:`flattenArguments` in that it only takes one argument and it only flattens items that are ``instanceof Array``. compare(flattenArray([1, [2, 3, [4, 5]]]), [1, 2, 3, 4, 5]) == 0 *Availability*: Available in MochiKit 1.4+ :mochidef:`forwardCall(name)`: Returns a function that forwards a method call to ``this.name(...)`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`isArrayLike(obj[, ...])`: Returns ``true`` if all given arguments are ``Array``-like (have a ``.length`` property and ``typeof(obj) == 'object'``) *Availability*: Available in MochiKit 1.3.1+ :mochidef:`isDateLike(obj[, ...])`: Returns ``true`` if all given arguments are ``Date``-like (have a ``.getTime()`` method) *Availability*: Available in MochiKit 1.3.1+ :mochidef:`isEmpty(obj[, ...])`: Returns ``true`` if all the given ``Array``-like or string arguments are empty ``(obj.length == 0)`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`isNotEmpty(obj[, ...])`: Returns ``true`` if all the given ``Array``-like or string arguments are not empty ``(obj.length > 0)`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`isNull(obj[, ...])`: Returns ``true`` if all arguments are ``null``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`isUndefinedOrNull(obj[, ...])`: Returns ``true`` if all arguments are undefined or ``null`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`itemgetter(name)`: Returns a ``function(obj)`` that returns ``obj[name]`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`items(obj)`: Return an ``Array`` of ``[propertyName, propertyValue]`` pairs for the given ``obj`` (in the order determined by ``for propName in obj``). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`keyComparator(key[, ...])`: A comparator factory that compares ``a[key]`` with ``b[key]``. e.g.:: var lst = ["a", "bbb", "cc"]; lst.sort(keyComparator("length")); assert( lst.toString() == "a,cc,bbb" ); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`keys(obj)`: Return an ``Array`` of the property names of an object (in the order determined by ``for propName in obj``). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`listMax(lst)`: Return the largest element of an ``Array``-like object, as determined by :mochiref:`compare`. This is a special form of :mochiref:`listMinMax`, specifically :mochiref:`partial(listMinMax, 1)`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`listMin(lst)`: Return the smallest element of an ``Array``-like object, as determined by :mochiref:`compare`. This is a special form of :mochiref:`listMinMax`, specifically :mochiref:`partial(listMinMax, -1)`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`listMinMax(which, lst)`: If ``which == -1`` then it will return the smallest element of the ``Array``-like ``lst``. This is also available as :mochiref:`listMin(lst)`. If ``which == 1`` then it will return the largest element of the ``Array``-like ``lst``. This is also available as :mochiref:`listMax(list)`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`map(fn, lst[, ...])`: Return a new array composed of the results of ``fn(x)`` for every ``x`` in ``lst``. If ``fn`` is ``null``, and only one sequence argument is given the identity function is used. :mochiref:`map(null, lst)` -> ``lst.slice()``; If ``fn`` is not ``null`` and more than one sequence argument is given, then one element from each sequence is used to build the argument list for ``fn``. :mochiref:`map(fn, p, q, ...)` -> ``[fn(p[0], q[0], ..), fn(p[1], q[1], ...), ...]`` If ``fn`` is ``null``, and more than one sequence is given as arguments, then the ``Array`` function is used. :mochiref:`map(null, p, q, ...)` -> :mochiref:`MochiKit.Iter.zip(p, q, ...)` -> ``[[p0, q0, ...], [p1, q1, ...], ...];`` Since this is a common idiom, :mochiref:`zip(p, q, ...)` is actually a shortcut for this. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`mean(lst[, ...])`: Returns the arithmetic mean (average) of the argument list, or an array. This function applies :mochiref:`flattenArguments()` to the argument list. *Availability*: Available in MochiKit 1.4+ :mochidef:`median(lst[, ...])`: Returns the median of the argument list, or an array. This function applies :mochiref:`flattenArguments()` to the argument list. *Availability*: Available in MochiKit 1.4+ :mochidef:`merge(obj[, ...])`: Create a new instance of ``Object`` that contains every property from all given objects. If a property is defined on more than one of the objects, the last property is used. This is a special form of :mochiref:`update(self, obj[, ...])`, specifically, it is defined as :mochiref:`partial(update, null)`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`method(self, func, ...)`: Alternate form of :mochiref:`bind` that takes the object before the function. These two calls are equivalent:: bind("method", myobject) method(myobject, "method") *Availability*: Available in MochiKit 1.3.1+ :mochidef:`methodcaller(name[, args...])`: Return a new function that calls a method on its argument, for example:: lst = map(methodcaller("toLowerCase"), ["THIS", "is", "LoWeRCaSe"]); assert( lst.join(" ") == "this is lowercase" ); *Availability*: Available in MochiKit 1.4+ :mochidef:`nameFunctions(namespace)`: Given a ``namespace`` (object or function) with a ``NAME`` property, find all methods in it and give them nice ``NAME`` properties too (for use with :mochiref:`repr`). e.g.:: namespace = { NAME: "Awesome", Dude: function () {} } nameFunctions(namespace); assert( namespace.Dude.NAME == 'Awesome.Dude' ); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`noop()`: A function that performs no operation. Use this where you would otherwise use ``(function () {})`` in order to avoid Internet Explorer cyclic garbage leakage. *Availability*: Available in MochiKit 1.4 :mochidef:`objEqual(a, b)`: Return ``true`` if ``compare(a, b) == 0`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`nodeWalk(node, visitor)`: Non-recursive generic node walking function (e.g. for a DOM). The walk order for nodeWalk is breadth first, meaning that all siblings will be visited before any children. ``node``: The initial node to be searched. ``visitor``: The visitor function, will be called as ``visitor(node)``, and should return an ``Array``-like of nodes to be searched next (e.g. ``node.childNodes``). Leaf nodes may return ``null`` or ``undefined``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`objMax(obj[, ...])`: Return the maximum object according to :mochiref:`compare` out of the given arguments. This is similar to :mochiref:`listMax`, except is uses the arguments instead of a given ``Array``-like. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`objMin(obj[, ...])`: Return the minimum object according to :mochiref:`compare` out of the given arguments. This is similar to :mochiref:`listMin`, except it uses the arguments instead of a given ``Array``-like. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`operator`: A table of JavaScript's operators for usage with :mochiref:`map`, :mochiref:`filter`, etc. Unary Logic Operators: +--------------------+--------------------------+-------------------+ | Operator | Implementation | Description | +====================+==========================+===================+ | ``truth(a)`` | ``!!a`` | Logical truth | +--------------------+--------------------------+-------------------+ | ``lognot(a)`` | ``!a`` | Logical not | +--------------------+--------------------------+-------------------+ | ``identity(a)`` | ``a`` | Logical identity | +--------------------+--------------------------+-------------------+ Unary Math Operators: +--------------------+--------------------------+---------------+ | Operator | Implementation | Description | +====================+==========================+===============+ | ``not(a)`` | ``~a`` | Bitwise not | +--------------------+--------------------------+---------------+ | ``neg(a)`` | ``-a`` | Negation | +--------------------+--------------------------+---------------+ Binary Operators: +-------------------+-------------------+-------------------------------+ | Operator | Implementation | Description | +===================+===================+===============================+ | ``add(a, b)`` | ``a + b`` | Addition | +-------------------+-------------------+-------------------------------+ | ``sub(a, b)`` | ``a - b`` | Subtraction | +-------------------+-------------------+-------------------------------+ | ``div(a, b)`` | ``a / b`` | Division | +-------------------+-------------------+-------------------------------+ | ``mod(a, b)`` | ``a % b`` | Modulus | +-------------------+-------------------+-------------------------------+ | ``mul(a, b)`` | ``a * b`` | Multiplication | +-------------------+-------------------+-------------------------------+ | ``and(a, b)`` | ``a & b`` | Bitwise and | +-------------------+-------------------+-------------------------------+ | ``or(a, b)`` | ``a | b`` | Bitwise or | +-------------------+-------------------+-------------------------------+ | ``xor(a, b)`` | ``a ^ b`` | Bitwise exclusive or | +-------------------+-------------------+-------------------------------+ | ``lshift(a, b)`` | ``a << b`` | Bitwise left shift | +-------------------+-------------------+-------------------------------+ | ``rshift(a, b)`` | ``a >> b`` | Bitwise signed right shift | +-------------------+-------------------+-------------------------------+ | ``zrshift(a, b)`` | ``a >>> b`` | Bitwise unsigned right shift | +-------------------+-------------------+-------------------------------+ Built-in Comparators: +---------------+-------------------+---------------------------+ | Operator | Implementation | Description | +===============+===================+===========================+ | ``eq(a, b)`` | ``a == b`` | Equals | +---------------+-------------------+---------------------------+ | ``ne(a, b)`` | ``a != b`` | Not equals | +---------------+-------------------+---------------------------+ | ``gt(a, b)`` | ``a > b`` | Greater than | +---------------+-------------------+---------------------------+ | ``ge(a, b)`` | ``a >= b`` | Greater than or equal to | +---------------+-------------------+---------------------------+ | ``lt(a, b)`` | ``a < b`` | Less than | +---------------+-------------------+---------------------------+ | ``le(a, b)`` | ``a <= b`` | Less than or equal to | +---------------+-------------------+---------------------------+ Strict Built-in Comparators: +---------------+-------------------+---------------------------+ | Operator | Implementation | Description | +===============+===================+===========================+ | ``seq(a, b)`` | ``a === b`` | Strict equals | +---------------+-------------------+---------------------------+ | ``sne(a, b)`` | ``a !== b`` | Strict not equals | +---------------+-------------------+---------------------------+ Extended Comparators (uses :mochiref:`compare`): +---------------+---------------------------+---------------------------+ | Operator | Implementation | Description | +===============+===========================+===========================+ | ``ceq(a, b)`` | ``compare(a, b) == 0`` | Equals | +---------------+---------------------------+---------------------------+ | ``cne(a, b)`` | ``compare(a, b) != 0`` | Not equals | +---------------+---------------------------+---------------------------+ | ``cgt(a, b)`` | ``compare(a, b) == 1`` | Greater than | +---------------+---------------------------+---------------------------+ | ``cge(a, b)`` | ``compare(a, b) != -1`` | Greater than or equal to | +---------------+---------------------------+---------------------------+ | ``clt(a, b)`` | ``compare(a, b) == -1`` | Less than | +---------------+---------------------------+---------------------------+ | ``cle(a, b)`` | ``compare(a, b) != 1`` | Less than or equal to | +---------------+---------------------------+---------------------------+ Binary Logical Operators: +-----------------------+-------------------+---------------------------+ | Operator | Implementation | Description | +=======================+===================+===========================+ | ``logand(a, b)`` | ``a && b`` | Logical and | +-----------------------+-------------------+---------------------------+ | ``logor(a, b)`` | ``a || b`` | Logical or | +-----------------------+-------------------+---------------------------+ | ``contains(a, b)`` | ``b in a`` | Has property (note order) | +-----------------------+-------------------+---------------------------+ *Availability*: Available in MochiKit 1.3.1+ :mochidef:`parseQueryString(encodedString[, useArrays=false])`: Parse a name=value pair URL query string into an object with a property for each pair. e.g.:: var args = parseQueryString("foo=value%20one&bar=two"); assert( args.foo == "value one" && args.bar == "two" ); If you expect that the query string will reuse the same name, then give ``true`` as a second argument, which will use arrays to store the values. e.g.:: var args = parseQueryString("foo=one&foo=two", true); assert( args.foo[0] == "one" && args.foo[1] == "two" ); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`partial(func, arg[, ...])`: Return a partially applied function, e.g.:: addNumbers = function (a, b) { return a + b; } addOne = partial(addNumbers, 1); assert(addOne(2) == 3); :mochiref:`partial` is a special form of :mochiref:`bind` that does not alter the bound ``self`` (if any). It is equivalent to calling:: bind(func, undefined, arg[, ...]); See the documentation for :mochiref:`bind` for more details about this facility. This could be used to implement, but is NOT currying. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`queryString(names, values)`: Creates a URL query string from a pair of ``Array``-like objects representing ``names`` and ``values``. Each name=value pair will be URL encoded by :mochiref:`urlEncode`. name=value pairs with a value of ``undefined`` or ``null`` will be skipped. e.g.:: var keys = ["foo", "bar"]; var values = ["value one", "two"]; assert( queryString(keys, values) == "foo=value%20one&bar=two" ); Alternate form 1: :mochiref:`queryString(domElement)` If :mochiref:`MochiKit.DOM` is loaded, one argument is given, and that argument is either a string or has a ``nodeType`` property greater than zero, then ``names`` and ``values`` will be the result of :mochiref:`MochiKit.DOM.formContents(domElement)`. Alternate form 2: :mochiref:`queryString({name: value, ...})` Note that when using the alternate form, the order of the name=value pairs in the resultant query string is dependent on how the particular JavaScript implementation handles ``for (..in..)`` property enumeration. When using the second alternate form, name=value pairs with ``typeof(value) == "function"`` are ignored. This is a workaround for the case where a poorly designed library has modified ``Object.prototype`` and inserted "convenience functions". Values that are Array-like will be expanded as if they were multiply defined HTML elements. For example:: assert( queryString({a: [1,2]}) === "a=1&a=2" ); Alternate form 2 (MochiKit 1.4+): :mochiref:`queryString([names, values])` This form behaves identically to :mochiref:`queryString(names, values)`, except it takes both arguments as a single Array. This mirrors the return value of :mochiref:`MochiKit.DOM.formContents`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`registerComparator(name, check, comparator[, override])`: Register a comparator for use with :mochiref:`compare`. ``name``: unique identifier describing the comparator. ``check``: ``function(a, b)`` that returns ``true`` if ``a`` and ``b`` can be compared with ``comparator``. ``comparator``: ``function(a, b)`` that returns: +-------+-----------+ | Value | Condition | +-------+-----------+ | 0 | a == b | +-------+-----------+ | 1 | a > b | +-------+-----------+ | -1 | a < b | +-------+-----------+ ``comparator`` is guaranteed to only be called if ``check(a, b)`` returns a ``true`` value. ``override``: if ``true``, then this will be made the highest precedence comparator. Otherwise, the lowest. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`registerJSON(name, check, simplifier[, override])`: Register a simplifier function for use with :mochiref:`serializeJSON`. ``name``: unique identifier describing the serialization. ``check``: ``function(obj)`` that returns ``true`` if ``obj`` can can be simplified for serialization by ``simplifier``. ``simplifier``: ``function(obj)`` that returns a simpler object that can be further serialized by :mochiref:`serializeJSON`. For example, you could simplify ``Date``-like objects to ISO 8601 timestamp strings with the following simplifier:: var simplifyDateAsISO = function (obj) { return toISOTimestamp(obj, true); }; registerJSON("DateLike", isDateLike, simplifyDateAsISO); ``simplifier`` is guaranteed to only be called if ``check(obj)`` returns a ``true`` value. ``override``: if ``true``, then this will be made the highest precedence serialization. Otherwise, the lowest. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`registerRepr(name, check, wrap[, override])`: Register a programmer representation function. :mochiref:`repr` functions should take one argument and return a string representation of it suitable for developers, primarily used when debugging. If ``override`` is given, it is used as the highest priority repr, otherwise it will be used as the lowest. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`repr(obj)`: Return a programmer representation for ``obj``. See the `Programmer Representation`_ overview for more information about this function. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`reverseKeyComparator(key)`: A comparator factory that compares ``a[key]`` with ``b[key]`` in reverse. e.g.:: var lst = ["a", "bbb", "cc"]; lst.sort(reverseKeyComparator("length")); assert(lst.toString() == "bbb,cc,a"); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`serializeJSON(anObject)`: Serialize ``anObject`` in the JSON [1]_ format, see `JSON Serialization`_ for the coercion rules. For unserializable objects (functions that do not have an adapter, ``__json__`` method, or ``json`` method), this will return ``undefined``. For those familiar with Python, JSON is similar in scope to pickle, but it can not handle recursive object graphs. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`setdefault(self, obj[, ...])`: Mutate ``self`` by adding all properties from other object(s) that it does not already have set. If ``self`` is ``null``, a new ``Object`` instance will be created and returned. This mutates *and returns* ``self``, be warned. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`typeMatcher(typ[, ...])`: Given a set of types (as string arguments), returns a ``function(obj[, ...])`` that will return ``true`` if the types of the given arguments are all members of that set. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`update(self, obj[, ...])`: Mutate ``self`` by replacing its key:value pairs with those from other object(s). Key:value pairs from later objects will overwrite those from earlier objects. If ``self`` is ``null``, a new ``Object`` instance will be created and returned. This mutates *and returns* ``self``, be warned. A version of this function that creates a new object is available as :mochiref:`merge(a, b[, ...])` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`updatetree(self, obj[, ...])`: Mutate ``self`` by replacing its key:value pairs with those from other object(s). If a given key has an object value in both ``self`` and ``obj``, then this function will be called recursively, updating instead of replacing that object. If ``self`` is ``null``, a new ``Object`` instance will be created and returned. This mutates *and returns* ``self``, be warned. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`urlEncode(unencoded)`: Converts ``unencoded`` into a URL-encoded string. In this implementation, spaces are converted to %20 instead of "+". e.g.:: assert( URLencode("1+2=2") == "1%2B2%3D2"); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`values(obj)`: Return an ``Array`` of the property values of an object (in the order determined by ``for propName in obj``). *Availability*: Available in MochiKit 1.4+ :mochidef:`xfilter(fn, obj[, ...])`: Returns a new ``Array`` composed of the arguments where ``fn(obj)`` returns a true value. If ``fn`` is ``null``, ``operator.truth`` will be used. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`xmap(fn, obj[, ...)`: Return a new ``Array`` composed of ``fn(obj)`` for every ``obj`` given as an argument. If ``fn`` is ``null``, ``operator.identity`` is used. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`zip(p, q, ...)`: Returns an array where the n-th element is an array of the n-th elements from each of the arrays p, q, ... This is equivalent to calling :mochiref:`map(fn, p, q, ...)` with ``null`` as the first argument. :mochiref:`zip(p, q, ...)` -> :mochiref:`map(null, p, q, ...)` -> ``[[p0, q0, ...], [p1, q1, ...], ...];`` *Availability*: Available in MochiKit 1.3.1+ See Also ======== .. [1] JSON, JavaScript Object Notation: http://json.org/ .. [2] Python's itertools module: http://docs.python.org/lib/module-itertools.html Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Selector.rst0000660000175000017500000001500611102215564017672 0ustar scottscott.. title:: MochiKit.Selector - Selecting elements by CSS selector syntax Name ==== MochiKit.Selector - Selecting elements by CSS selector syntax Synopsis ======== :: MochiKit.Base.map(MochiKit.Visual.fade, $$('p.fademe')); Description =========== MochiKit.Selector provides utilities to select elements by CSS selector syntax. In particular it provides the :mochiref:`$$` function. Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.DOM` - :mochiref:`MochiKit.Iter` Overview ======== This module provides facilities to select childs of a DOM node by using CSS selector syntax. In particular, it provides the :mochiref:`$$` function, which performs such a selection on the current document. Many of CSS3 [1]_ selectors are supported: - Select by tag name (``A``) - Select by class (``.theclass``) - Select by id (``#someid``) - Combinators - Descendant: ``E F`` - Child: ``E > F`` - Immediate following sibling: ``E + F`` - Following sibling: ``E ~ F`` - Attribute selectors - simple "has attribute" (without operator) - ``=`` equal - ``!=`` not equal (not in CSS std.) - ``~=`` word containment - ``^=`` starts-with - ``$=`` ends-with - ``*=`` substring containment - ``|=`` first part of hyphen deleimited (eg. lang|="en" matches lang="en-US") - Pseudo-classes - ``:nth-child``, ``:nth-last-child``, ``:first-child``, ``:last-child``, ``:only-child``, ``:empty``, ``:enabled``, ``:disabled``, ``:checked``, ``:not()`` - Deprecated Pseudo-classes (to be removed in 1.5) - ``:root``, ``:nth-of-type``, ``:nth-last-of-type``, ``:first-of-type``, ``:last-of-type``, ``:only-of-type`` Multiple selectors can be concatenated, like this: ``P.quote[author~='Torvalds']``, in which case elements matching *all* the selectors are returned. Furthermore, such concatenations can be *combined* by joining them with spaces and combinators. This invokes the regular CSS behaviour of matching parts of the combination in sequence, starting off each part from the elements returned by the preceeding part. For the ``:nth-*`` pseudoclasses, the ``an+b`` syntax is partially supported, specifically a and b must be non-negative and only a is optional (this differs from the CSS std.) Also, ``odd`` and ``even`` are supported, e.g. ``table tr:nth-child(odd)`` gives you every other row of table starting with the first one. For further documentation of CSS selectors, refer to the W3C CSS standard. [1]_ The original version of this module was ported from Prototype. **Note:** This module is currently experimental and API stability cannot be fully guaranteed. The implementation is scheduled to be replaced with a new faster version (now in development) during the MochiKit 1.5 development cycle. **Note:** Due to how Internet Explorer handles node attributes, some attribute selectors may not work as expected. In particular ``a[title]`` will not work as all ``A`` elements in the Internet Explorer DOM model have a title attribute regardless of whether it's specified in the markup or not. API Reference ============= Functions --------- :mochidef:`findDocElements(expression[, ...])`: Performs a selection on the active document. Equivalent to ``findChildElements(MochiKit.DOM.currentDocument(), [expression, ...])`` *Availability*: Available in MochiKit 1.4+ :mochidef:`findChildElements(element, expressions)`: Traverses the child nodes of ``element`` and returns the subset of those that match any of the selector expressions in ``expressions``. Each expression can be a combination of simple expressions, by concatenating them with spaces or combinators. In that case, normal CSS rules apply, each simple expression is evaluated in turn and the results of that one is used as the scope for the succeeding expression (see :mochiref:`Selector.findElements`). Finally, the results of the last simple expression is returned as the search result. *Availability*: Available in MochiKit 1.4+ :mochidef:`$$(expression[, ...])`: An alias to ``findDocElements``. *Availability*: Available in MochiKit 1.4+ Constructors ------------- :mochidef:`Selector(simpleExpression)`: An object storing the parsed version of a simple CSS selector expression and providing functions for executing searches. *Simple* means that the expression is not a combination of expressions, i.e. it does not contain any spaces. Usually the user would not instantiate or use this object directly, but heres how:: var selector = new MochiKit.Selector.Selector('#someelementid'); var searchResults = selector.findElements(rootElement); *Deprecated*: Use :mochiref:`findChildElements` instead. The Selector class will be removed in version 1.5. *Availability*: Available in MochiKit 1.4+ :mochidef:`Selector.findElements(scope[, axis=""])`: Performs a search on ``scope``. The value of axis controls what relatives of ``scope`` are considered. ``scope``: A DOM node that acts as a starting point for the search. ``axis``: One of ``">"``, ``"+"``, ``"~"`` or the empty string (default). If the empty string, all descendant nodes of ``scope`` are tested against the expression. If ``>`` only direct child nodes of ``scope`` are tested, if ``+`` only the next sibling (if any) of ``scope`` is tested and if ``~`` all succeeding siblings of ``scope`` are tested. *Deprecated*: Use :mochiref:`findChildElements` instead. The Selector class will be removed in version 1.5. *Availability*: Available in MochiKit 1.4+ See Also ======== .. [1] CSS Selectors Level 3 (Last Call, oct. 2006): http://www.w3.org/TR/2005/WD-css3-selectors-20051215/ Authors ======= - Arnar Birgisson - Thomas Herve - Originally ported from Prototype Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php Based on Prototype, (c) 2005 Sam Stephenson, available under the `Prototype license`_ .. _`Prototype license`: http://dev.rubyonrails.org/browser/spinoffs/prototype/LICENSE?rev=3362 MochiKit-1.4.2/doc/rst/MochiKit/Style.rst0000660000175000017500000002336711102662100017213 0ustar scottscott.. title:: MochiKit.Style - painless Style manipulation API Name ==== MochiKit.Style - painless Style manipulation API Synopsis ======== :: var messagePos = getElementPosition('message'); var messageSize = getElementDimensions('message'); var notifyPos = new MochiKit.Style.Coordinates( messagePos.x + messageSize.w + 10, messagePos.y); setElementPosition('notify', notifyPos); Description =========== Refactored from :mochiref:`MochiKit.DOM`. Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.DOM` Overview ======== Refactored from :mochiref:`MochiKit.DOM`. Element Visibility ------------------ The :mochiref:`hideElement` and :mochiref:`showElement` functions are provided as a convenience, but only work for elements that are ``display: block``. For a general solution to showing, hiding, and checking the explicit visibility of elements, we recommend using a solution that involves a little CSS. Here's an example:: MochiKit doesn't ship with such a solution, because there is no reliable and portable method for adding CSS rules on the fly with JavaScript. API Reference ============= Functions --------- :mochidef:`getStyle(element, cssSelector)`: Looks up a CSS property for the given element. The element can be specified as either a string with the element's ID or the element object itself. ``cssSelector``: The CSS selector, e.g. ``background-color``. *Availability*: Available in MochiKit 1.4+ :mochidef:`setStyle(element, styles)`: Set CSS properties on a the given element. The element can be specified as either a string with the element's ID or the element object itself. ``styles``: Dictionnary holding CSS properties to set, e.g. ``{'background-color': 'red', 'opacity': 0.5}``. *Availability*: Available in MochiKit 1.4+ :mochidef:`setOpacity(element, opacity)`: Sets ``opacity`` for ``element``. Valid ``opacity`` values range from 0 (invisible) to 1 (opaque). ``element`` is looked up with :mochiref:`getElement`, so string identifiers are also acceptable. *Availability*: Available in MochiKit 1.4+ :mochidef:`getElementDimensions(element[, contentSize=false])`: Return the absolute pixel width and height of ``element`` as an object with ``w`` and ``h`` properties, or ``undefined`` if ``element`` is not in the document. The size will include padding and border, but not margins, unless ``contentSize`` is set to true, in which case the size will be only the content size, without padding and border. ``element`` may be specified as a string to be looked up with :mochiref:`getElement`, a DOM element, or trivially as an object with ``w`` and/or ``h`` properties. *Availability*: Available in MochiKit 1.4+ :mochidef:`setElementDimensions(element, dimensions[, units='px'])`: Sets the dimensions of ``element`` in the document from an object with ``w`` and ``h`` properties. Warning: IE in quirks-mode seems to behave strange when you set the height off an element containing text to 0. You can workaround this by setting the value of visibly/display. ``element``: A reference to the DOM element to update (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``dimensions``: An object with ``w`` and ``h`` properties. You can also specify only one property. ``units``: Optionally set the units to use, default is ``px`` *Availability*: Available in MochiKit 1.4+ :mochidef:`getElementPosition(element[, relativeTo={x: 0, y: 0}])`: Return the absolute pixel position of ``element`` in the document as an object with ``x`` and ``y`` properties, or ``undefined`` if ``element`` is not in the document. ``element`` may be specified as a string to be looked up with :mochiref:`getElement`, a DOM element, or trivially as an object with ``x`` and/or ``y`` properties. If ``relativeTo`` is given, then its coordinates are subtracted from the absolute position of ``element``, e.g.:: var elemPos = getElementPosition(elem); var anotherElemPos = getElementPosition(anotherElem); var relPos = getElementPosition(elem, anotherElem); assert( relPos.x == (elemPos.x - anotherElemPos.x) ); assert( relPos.y == (elemPos.y - anotherElemPos.y) ); ``relativeTo`` may be specified as a string to be looked up with :mochiref:`getElement`, a DOM element, or trivially as an object with ``x`` and/or ``y`` properties. *Availability*: Available in MochiKit 1.4+ :mochidef:`setElementPosition(element, position[, units='px'])`: Sets the absolute position of ``element`` in the document from an object with ``x`` and ``y`` properties. ``element``: A reference to the DOM element to update (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``position``: An object with ``x`` and ``y`` properties. You can also specify only one property. ``units``: Optionally set the units to use, default is ``px`` *Availability*: Available in MochiKit 1.4+ :mochidef:`makePositioned(element)`: Ensure that ``element.style.position`` is set to ``"relative"`` if it is not set or is ``"static"``. If ``element`` is a string, then it will be looked up with :mochiref:`getElement`. *Availability*: Available in MochiKit 1.4.1+ :mochidef:`undoPositioned(element)`: Restore the setting of ``element.style.position`` set by :mochiref:`makePositioned(element)`. If ``element`` is a string, then it will be looked up with :mochiref:`getElement`. *Availability*: Available in MochiKit 1.4.1+ :mochidef:`makeClipping(element)`: Ensure that ``element.style.overflow = 'hidden'``. If ``element`` is a string, then it will be looked up with :mochiref:`getElement`. Returns the original values of ``overflow``, ``overflow-y`` and ``overflow-y`` so that they may be restored with :mochiref:`undoClipping(element, overflow)`. *Availability*: Available in MochiKit 1.4.1+ :mochidef:`undoClipping(element, overflow)`: Restore the setting of ``element.style.overflow`` set by :mochiref:`makeClipping(element)`. If ``element`` is a string, then it will be looked up with :mochiref:`getElement`. *Availability*: Available in MochiKit 1.4.1+ :mochidef:`setDisplayForElement(display, element[, ...])`: Change the ``style.display`` for the given element(s). Usually used as the partial forms: - :mochiref:`showElement(element, ...)` - :mochiref:`hideElement(element, ...)` Elements are looked up with :mochiref:`getElement`, so string identifiers are acceptable. For information about the caveats of using a ``style.display`` based show/hide mechanism, and a CSS based alternative, see `Element Visibility`_. *Availability*: Available in MochiKit 1.4+ :mochidef:`showElement(element, ...)`: Partial form of :mochiref:`setDisplayForElement`, specifically:: partial(setDisplayForElement, "block") For information about the caveats of using a ``style.display`` based show/hide mechanism, and a CSS based alternative, see `Element Visibility`_. *Availability*: Available in MochiKit 1.4+ :mochidef:`hideElement(element, ...)`: Partial form of :mochiref:`setDisplayForElement`, specifically:: partial(setDisplayForElement, "none") For information about the caveats of using a ``style.display`` based show/hide mechanism, and a CSS based alternative, see `Element Visibility`_. *Availability*: Available in MochiKit 1.4+ :mochidef:`getViewportDimensions()`: Return the pixel width and height of the viewport as an object with ``w`` and ``h`` properties. *Availability*: Available in MochiKit 1.4+ :mochidef:`getViewportPosition()`: Return the pixel position of the viewport inside the window, as a :mochiref:`Coordinates` object. *Availability*: Available in MochiKit 1.4+ Objects ------- :mochidef:`Coordinates(x, y)`: Constructs an object with ``x`` and ``y`` properties. ``obj.toString()`` returns something like ``{x: 0, y: 42}`` for debugging. *Availability*: Available in MochiKit 1.4+ :mochidef:`Dimensions(w, h)`: Constructs an object with ``w`` and ``h`` properties. ``obj.toString()`` returns something like ``{w: 0, h: 42}`` for debugging. *Availability*: Available in MochiKit 1.4+ Authors ======= - Bob Ippolito - Beau Hartshorne Copyright ========= Copyright 2005-2006 Bob Ippolito , and Beau Hartshorne . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Logging.rst0000660000175000017500000002212111102215564017474 0ustar scottscott.. title:: MochiKit.Logging - we're all tired of alert() Name ==== MochiKit.Logging - we're all tired of alert() Synopsis ======== :: log("INFO messages are so boring"); logDebug("DEBUG messages are even worse"); log("good thing I can pass", objects, "conveniently"); Description =========== MochiKit.Logging steals some ideas from Python's logging module [1]_, but completely forgot about the Java [2]_ inspiration. This is a KISS module for logging that provides enough flexibility to do just about anything via listeners, but without all the cruft. Dependencies ============ - :mochiref:`MochiKit.Base` Overview ======== Native Console Logging ---------------------- As of MochiKit 1.3, the default logger will log all messages to your browser's native console. This is currently supported in Safari, Opera 9, and Firefox when the `FireBug`_ extension is installed. MochiKit 1.4 adds support for the relevant APIs for Internet Explorer (the Debugger and the Atlas framework, see `here`__). .. __: http://www.nikhilk.net/Entry.aspx?id=93 .. _`FireBug`: http://www.joehewitt.com/software/firebug/ To disable this behavior:: MochiKit.Logging.logger.useNativeConsole = false; Bookmarklet Based Debugging --------------------------- JavaScript is at a serious disadvantage without a standard console for "print" statements. Everything else has one. The closest thing that you get in a browser environment is the ``alert`` function, which is absolutely evil. This leaves you with one reasonable solution: do your logging in the page somehow. The problem here is that you don't want to clutter the page with debugging tools. The solution to that problem is what we call BBD, or Bookmarklet Based Debugging [3]_. Simply create a bookmarklet for `javascript:MochiKit.Logging.logger.debuggingBookmarklet()`__, and whack it whenever you want to see what's in the logger. Of course, this means you must drink the MochiKit.Logging kool-aid. It's tangy and sweet, don't worry. .. __: javascript:MochiKit.Logging.logger.debuggingBookmarklet() Currently this uses :mochiref:`MochiKit.LoggingPane` if loaded and otherwise falls back to ugly ``alert`` messages. API Reference ============= Constructors ------------ :mochidef:`LogMessage(num, level, info)`: Properties: ``num``: Identifier for the log message ``level``: Level of the log message (``"INFO"``, ``"WARN"``, ``"DEBUG"``, etc.) ``info``: All other arguments passed to log function as an ``Array`` ``timestamp``: ``Date`` object timestamping the log message *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger([maxSize])`: A basic logger object that has a buffer of recent messages plus a listener dispatch mechanism for "real-time" logging of important messages. ``maxSize`` is the maximum number of entries in the log. If ``maxSize >= 0``, then the log will not buffer more than that many messages. So if you don't like logging at all, be sure to pass ``0``. There is a default logger available named "logger", and several of its methods are also global functions: ================== ============= ``logger.log`` -> :mochiref:`log` ``logger.debug`` -> :mochiref:`logDebug` ``logger.warning`` -> :mochiref:`logWarning` ``logger.error`` -> :mochiref:`logError` ``logger.fatal`` -> :mochiref:`logFatal` ================== ============= *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger.prototype.addListener(ident, filter, listener)`: Add a listener for log messages. ``ident`` is a unique identifier that may be used to remove the listener later on. ``filter`` can be one of the following: ``null``: ``listener(msg)`` will be called for every log message received. ``string``: :mochiref:`logLevelAtLeast(filter)` will be used as the function (see below). ``function``: ``filter(msg)`` will be called for every msg, if it returns true then ``listener(msg)`` will be called. ``listener`` is a function that takes one argument, a log message. A log message is an object (:mochiref:`LogMessage` instance) that has at least these properties: ``num``: A counter that uniquely identifies a log message (per-logger) ``level``: A string or number representing the log level. If string, you may want to use ``LogLevel[level]`` for comparison. ``info``: An Array of objects passed as additional arguments to the ``log`` function. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger.prototype.baseLog(level, message[, ...])`: The base functionality behind all of the log functions. The first argument is the log level as a string or number, and all other arguments are used as the info list. This function is available partially applied as: ============== ========= Logger.debug 'DEBUG' Logger.log 'INFO' Logger.error 'ERROR' Logger.fatal 'FATAL' Logger.warning 'WARNING' ============== ========= For the default logger, these are also available as global functions, see the :mochiref:`Logger` constructor documentation for more info. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger.prototype.clear()`: Clear all messages from the message buffer. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger.prototype.debuggingBookmarklet()`: Display the contents of the logger in a useful way for browsers. Currently, if :mochiref:`MochiKit.LoggingPane` is loaded, then a pop-up :mochiref:`MochiKit.LoggingPane.LoggingPane` will be used. Otherwise, it will be an alert with :mochiref:`Logger.prototype.getMessageText()`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger.prototype.dispatchListeners(msg)`: Dispatch a log message to all listeners. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger.prototype.getMessages([howMany])`: Returns a list of messages from the message buffer, ordered from the oldest to the newest message. If ``howMany`` is specified, only the last ``howMany`` messages are returned. Otherwise all messages in the buffer are returned. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger.prototype.getMessageText([howMany])`: Get a string representing up to the last ``howMany`` messages in the message buffer. The default is ``30``. The message looks like this:: LAST {messages.length} MESSAGES: [{msg.num}] {msg.level}: {m.info.join(' ')} [{msg.num}] {msg.level}: {m.info.join(' ')} ... If you want some other format, use :mochiref:`Logger.prototype.getMessages` and do it yourself. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`Logger.prototype.removeListener(ident)`: Remove a listener using the ident given to :mochiref:`Logger.prototype.addListener` *Availability*: Available in MochiKit 1.3.1+ Functions --------- :mochidef:`alertListener(msg)`: Ultra-obnoxious ``alert(...)`` listener *Availability*: Available in MochiKit 1.3.1+ :mochidef:`log(message[, info[, ...]])`: Log an INFO message to the default logger *Availability*: Available in MochiKit 1.3.1+ :mochidef:`logDebug(message[, info[, ...]])`: Log a DEBUG message to the default logger *Availability*: Available in MochiKit 1.3.1+ :mochidef:`logError(message[, info[, ...]])`: Log an ERROR message to the default logger *Availability*: Available in MochiKit 1.3.1+ :mochidef:`logFatal(message[, info[, ...]])`: Log a FATAL message to the default logger *Availability*: Available in MochiKit 1.3.1+ :mochidef:`logLevelAtLeast(minLevel)`: Return a function that will match log messages whose level is at least minLevel *Availability*: Available in MochiKit 1.3.1+ :mochidef:`logWarning(message[, info[, ...]])`: Log a WARNING message to the default logger *Availability*: Available in MochiKit 1.3.1+ See Also ======== .. [1] Python's logging module: http://docs.python.org/lib/module-logging.html .. [2] PEP 282, where they admit all of the Java influence: http://www.python.org/peps/pep-0282.html .. [3] Original Bookmarklet Based Debugging blather: http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/ Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Format.rst0000660000175000017500000002144311102215564017344 0ustar scottscott.. title:: MochiKit.Format - string formatting goes here Name ==== MochiKit.Format - string formatting goes here Synopsis ======== :: assert( truncToFixed(0.12345, 4) == "0.1234" ); assert( roundToFixed(0.12345, 4) == "0.1235" ); assert( twoDigitAverage(1, 0) == "0" ); assert( twoDigitFloat(1.2345) == "1.23" ); assert( twoDigitFloat(1) == "1" ); assert( percentFormat(1.234567) == "123.46%" ); assert( numberFormatter("###,###%")(125) == "12,500%" ); assert( numberFormatter("##.000")(1.25) == "1.250" ); Description =========== Formatting strings and stringifying numbers is boring, so a couple useful functions in that domain live here. Dependencies ============ None. Overview ======== Formatting Numbers ------------------ MochiKit provides an extensible number formatting facility, modeled loosely after the Number Format Pattern Syntax [1]_ from Java. :mochiref:`numberFormatter(pattern[, placeholder=""[, locale="default"])` returns a function that converts Number to string using the given information. ``pattern`` is a string consisting of the following symbols: +-----------+---------------------------------------------------------------+ | Symbol | Meaning | +===========+===============================================================+ | ``-`` | If given, used as the position of the minus sign | | | for negative numbers. If not given, the position | | | to the left of the first number placeholder is used. | +-----------+---------------------------------------------------------------+ | ``#`` | The placeholder for a number that does not imply zero | | | padding. | +-----------+---------------------------------------------------------------+ | ``0`` | The placeholder for a number that implies zero padding. | | | If it is used to the right of a decimal separator, it | | | implies trailing zeros, otherwise leading zeros. | +-----------+---------------------------------------------------------------+ | ``,`` | The placeholder for a "thousands separator". May be used | | | at most once, and it must be to the left of a decimal | | | separator. Will be replaced by ``locale.separator`` in the | | | result (the default is also ``,``). | +-----------+---------------------------------------------------------------+ | ``.`` | The decimal separator. The quantity of ``#`` or ``0`` | | | after the decimal separator will determine the precision of | | | the result. If no decimal separator is present, the | | | fractional precision is ``0`` -- meaning that it will be | | | rounded to the nearest integer. | +-----------+---------------------------------------------------------------+ | ``%`` | If present, the number will be multiplied by ``100`` and | | | the ``%`` will be replaced by ``locale.percent``. | +-----------+---------------------------------------------------------------+ API Reference ============= Functions --------- :mochidef:`formatLocale(locale="default")`: Return a locale object for the given locale. ``locale`` may be either a string, which is looked up in the ``MochiKit.Format.LOCALE`` object, or a locale object. If no locale is given, ``LOCALE.default`` is used (equivalent to ``LOCALE.en_US``). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`lstrip(str, chars="\\s")`: Returns a string based on ``str`` with leading whitespace stripped. If ``chars`` is given, then that expression will be used instead of whitespace. ``chars`` should be a string suitable for use in a ``RegExp`` ``[character set]``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`numberFormatter(pattern, placeholder="", locale="default")`: Return a function ``formatNumber(aNumber)`` that formats numbers as a string according to the given pattern, placeholder and locale. ``pattern`` is a string that describes how the numbers should be formatted, for more information see `Formatting Numbers`_. ``locale`` is a string of a known locale (en_US, de_DE, fr_FR, default) or an object with the following fields: +-----------+-----------------------------------------------------------+ | separator | The "thousands" separator for this locale (en_US is ",") | +-----------+-----------------------------------------------------------+ | decimal | The decimal separator for this locale (en_US is ".") | +-----------+-----------------------------------------------------------+ | percent | The percent symbol for this locale (en_US is "%") | +-----------+-----------------------------------------------------------+ *Availability*: Available in MochiKit 1.3.1+ :mochidef:`percentFormat(aNumber)`: Return a string representation of ``aNumber * 100``, rounded to a maximum precision of 2 fractional digits. Roughly equivalent to: ``sprintf("%.2f%%", aNumber * 100)`` In new code, you probably want to use: :mochiref:`numberFormatter("#.##%")(aNumber)` instead. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`roundToFixed(aNumber, precision)`: Return a string representation of ``aNumber``, rounded to ``precision`` digits with trailing zeros. This is similar to ``Number.toFixed(aNumber, precision)``, but this has implementation consistent rounding behavior (some versions of Safari round 0.5 down!) and also includes preceding ``0`` for numbers less than ``1`` (Safari, again). For example, :mochiref:`roundToFixed(0.1357, 2)` returns ``0.14`` on every supported platform, where some return ``.13`` for ``(0.1357).toFixed(2)``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`rstrip(str, chars="\\s")`: Returns a string based on ``str`` with trailing whitespace stripped. If ``chars`` is given, then that expression will be used instead of whitespace. ``chars`` should be a string suitable for use in a ``RegExp`` ``[character set]``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`strip(str, chars="\\s")`: Returns a string based on ``str`` with leading and trailing whitespace stripped (equivalent to :mochiref:`lstrip(rstrip(str, chars), chars)`). If ``chars`` is given, then that expression will be used instead of whitespace. ``chars`` should be a string suitable for use in a ``RegExp`` ``[character set]``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`truncToFixed(aNumber, precision)`: Return a string representation of ``aNumber``, truncated to ``precision`` digits with trailing zeros. This is similar to ``aNumber.toFixed(precision)``, but this truncates rather than rounds and has implementation consistent behavior for numbers less than 1. Specifically, :mochiref:`truncToFixed(aNumber, precision)` will always have a preceding ``0`` for numbers less than ``1``. For example, :mochiref:`truncToFixed(0.1357, 2)` returns ``0.13``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`twoDigitAverage(numerator, denominator)`: Calculate an average from a numerator and a denominator and return it as a string rounded to a maximum precision of two fractional digits (e.g. "1.23"). If the denominator is 0, "0" will be returned instead of ``NaN``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`twoDigitFloat(aNumber)`: Return a string representation of ``aNumber``, rounded to a maximum precision of 2 fractional digits. This is a variation of :mochiref:`roundToFixed(aNumber, 2)` that removes trailing zeros from the fractional part. For example, ``twoDigitFloat(0.1357)`` returns ``0.14`` and ``twoDigitFloat(12.00)`` returns ``12``. In new code, you probably want to use: :mochiref:`numberFormatter("#.##")(aNumber)` instead. *Availability*: Available in MochiKit 1.3.1+ See Also ======== .. [1] Java Number Format Pattern Syntax: http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Position.rst0000660000175000017500000000126711102215564017722 0ustar scottscott.. title:: MochiKit.Position - DOM Position manipulation API Name ==== MochiKit.Position - DOM Position manipulation API Synopsis ======== This module is experimental and is present in MochiKit 1.4+ only. No functions are currently exported from this module. Documentation is forthcoming. Copyright ========= Copyright 2005-2006 Bob Ippolito , and others. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/VersionHistory.rst0000660000175000017500000004461011113645622021130 0ustar scottscott2008-11-27 v1.4.2 (bug fix release) - Changed default packed version to contain all modules (since easy customization is now available). - More fixes in MochiKit.Style.getElementDimensions for IE and hidden elements (#325). - Fixed issue in MochiKit.Style.getViewportDimensions when called within the document HEAD. - Fixed MochiKit.DOM.coerceToDOM() handling of arrays when MochiKit.Iter is not loaded (#328). 2008-11-02 v1.4.1 (bug fix release) - Added export of deprecated MochiKit.DOM.computedStyle function (#324). - Fixed issue in MochiKit.Style.getElementDimensions when elements are hidden due to CSS class definitions (#325). - Moved makePositioned, undoPositioned, makeClipping and undoClipping from MochiKit.DOM to MochiKit.Style due to circular dependency (#327). - Fixed makeClipping and undoClipping to handle overflow-x and overflow-y styles correctly (#326). - Fixed issue with Event.relatedTarget() sometimes returning XUL elements in Mozilla-based browsers (#322). 2008-10-21 v1.4 - Added pt_BR to MochiKit.Format.LOCALE. - MochiKit.Async now sets the "X-Requested-With: XMLHttpRequest" header, a de facto standard (Prototype, jQuery, Mootools). - MochiKit.Signal custom handlers no longer cause callbacks to get re-bound to the source if they were previously bound. - Fixed MochiKit.Signal.signal re-entrancy bug that could cause recently disconnected slots to get signaled. - MochiKit.Base.evalJSON will now evaluate JSON that is wrapped in a ``/* comment block */``. - MochiKit.Color's HSV to RGB conversion code fixed to return the correct value (hsv.v for RGB values) in cases where saturation === 0. - doXHR workaround for a Mozilla bug when calling XMLHttpRequest in certain situations. Always wraps call in a callLater(0, doXHR, url, opts). - parseQueryString will now parse values with embedded "=" - Workaround for a Safari DOM crash when using MochiKit.Iter.list. http://bugs.webkit.org/show_bug.cgi?id=12191 - New removeNodeAttribute function in MochiKit.DOM. - MochiKit.Async.doXHR and dependent functions now accept 201 CREATED and 204 NO CONTENT as valid. - MochiKit.DOM.formContents now treats option tags the same way that form posts do in the case of missing and empty string value attributes, even in IE. - MochiKit.Base.queryString now accepts third queryString([names, values]) form. - MochiKit.DOM.formContents now defaults to document.body if no element is given. - New MochiKit.Selector module (still somewhat experimental) - MochiKit.LoggingPane fixes for Internet Explorer - MochiKit.DOM now creates XHTML nodes in XUL documents. - MochiKit.LoggingPane now works on pages with '#' in the URL on IE - New MochiKit.Async.doXHR as a convenient method for doing custom XMLHttpRequests (e.g. extra headers, overrideMimeType, etc.) - New __connect__ protocol for MochiKit.Signal.connect source notifications - Added colSpan, bgColor to the list of DOM renames for Internet Explorer - New MochiKit.Signal.disconnectAllTo function - MochiKit.Base.parseQueryString now accepts leading question mark - New MochiKit.Base.values function - Fixed MochiKit.Signal.disconnect when called from a signal handler invoked by MochiKit.Signal.signal - parseQueryString now splits on HTML entities equivalent to ampersand as well - Better XHTML compatibility (removed obvious cases where uppercase tagName or nodeName was assumed) - MochiKit.Base.queryString now handles array values in the same way HTML forms handle multiple elements of the same name. - MochiKit.Base.parseQueryString now returns {} for empty query string instead of {"": "undefined"} - MochiKit.DOM.formContents now handles option value="" correctly. - MochiKit.DOM now checks for undefined className. - MochiKit.Iter.groupby() now uses compare() to group rather than == and != - serializeJSON no longer serializes undefined, as per the JSON spec - Fixed an infinite recursion bug in serializeJSON if an adapter returns the object itself. - Fixed vertical tab and control char encoding in serializeJSON (#313). - New MochiKit.Base.operator.seq and sne to support strict comparison - MochiKit.Base.isArrayLike no longer returns true for DOM text nodes - Added readonly-readOnly to the list of DOM renames for Internet Explorer - New MochiKit.Signal event method: confirmUnload (sets returnValue for onbeforeunload) - Fix interpreter help() function for Firefox and IE - API version compatibility notes added - New MochiKit.Base functions methodcaller and compose - Support IE-based native console logging (Debugger, Atlas) - Refactored style functions from MochiKit.DOM to MochiKit.Style - MochiKit.Async.DeferredList is now a proper Deferred - MochiKit.DOM.formContents now supports SELECT multiple tags - Re-use StopIteration Error if the browser already has it - Workaround IE type="" bug for INPUT elements - Allow LoggingPane to work in IE with hyphen-containing URLs - Replace percents for Safari native logging to avoid crashing - New MochiKit.DOM.coerceToDOM .dom(node) / .__dom__(node) protocol - MochiKit.DOM's MochiKit.Iter dependency is now optional - Added expand all link to the documentation index - Added MochiKit.DOM.isChildNode function. - Added synthesizing for onmouseenter/onmouseleave - Added animation functions and classes to MochiKit.Visual. - Added MochiKit.Style.getElementDimensions support for calculating the actual content size (without padding and borders). - Added MochiKit.DOM.insertSiblingNodesBefore, getFirstElementByTagAndClassName, getFirstParentByTagAndClassName, makeClipping, makePositioned, undoClipping, undoPositioned and removeEmptyTextNodes functions. - Added MochiKit.Base.bindLate, camelize, flattenArray, mean, median and noop functions. - New MochiKit.DragAndDrop module for drag and drop handling. - New MochiKit.Sortable module for lists sortable with drag and drop. - Changed MochiKit.Signal.connect to use late function binding also for non-DOM signals (#307). - Fixed MochiKit.Color.isColor when symbols not exported (#296). - Added support for inclusion in SVG files (#290). - Fixed rounding errors in MochiKit.Format.twoDigitFloat (#275). - Fixed MochiKit.Logging to convert log levels to strings (#273). - Fixed MochiKit.Iter.forEach and iextend for array-like objects with and iter function (#268). 2006-04-29 v1.3.1 (bug fix release) - Fix sendXMLHttpRequest sendContent regression - Internet Explorer fix in MochiKit.Logging (printfire exception) - Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async 2006-04-26 v1.3 "warp zone" - IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export) - IMPORTANT: Renamed MochiKit.Base.find to findValue (for export) - New MochiKit.Base.method as a convenience form of bind that takes the object before the method - New MochiKit.Base.flattenArguments for flattening a list of arguments to a single Array - Refactored MochiRegExp example to use MochiKit.Signal - New key_events example demonstrating use of MochiKit.Signal's key handling capabilities. - MochiKit.DOM.createDOM API change for convenience: if attrs is a string, null is used and the string will be considered the first node. This allows for the more natural P("foo") rather than P(null, "foo"). - MochiKit Interpreter example refactored to use MochiKit.Signal and now provides multi-line input and a help() function to get MochiKit function signature from the documentation. - Native Console Logging for the default MochiKit.Logging logger - New MochiKit.Async.DeferredList, gatherResults, maybeDeferred - New MochiKit.Signal example: draggable - Added sanity checking to Deferred to ensure that errors happen when chaining is used incorrectly - Opera sendXMLHttpRequest fix (sends empty string instead of null by default) - Fix a bug in MochiKit.Color that incorrectly generated hex colors for component values smaller than 16/255. - Fix a bug in MochiKit.Logging that prevented logs from being capped at a maximum size - MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof Error, so that the errback chain is used instead of the callback chain. - MochiKit.DOM.appendChildNodes and associated functions now append iterables in the correct order. - New MochiKit-based SimpleTest test runner as a replacement for Test.Simple - MochiKit.Base.isNull no longer matches undefined - example doctypes changed to HTML4 - isDateLike no longer throws error on null - New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt - updated elementDimensions to calculate width from offsetWidth instead of clientWidth - formContents now works with FORM tags that have a name attribute - Documentation now uses MochiKit to generate a function index 2006-01-26 v1.2 "the ocho" - Fixed MochiKit.Color.Color.lighterColorWithLevel - Added new MochiKit.Base.findIdentical function to find the index of an element in an Array-like object. Uses === for identity comparison. - Added new MochiKit.Base.find function to find the index of an element in an Array-like object. Uses compare for rich comparison. - MochiKit.Base.bind will accept a string for func, which will be immediately looked up as self[func]. - MochiKit.DOM.formContents no longer skips empty form elements for Zope compatibility - MochiKit.Iter.forEach will now catch StopIteration to break - New MochiKit.DOM.elementDimensions(element) for determining the width and height of an element in the document - MochiKit.DOM's initialization is now compatible with HTMLUnit + JWebUnit + Rhino - MochiKit.LoggingPane will now re-use a ``_MochiKit_LoggingPane`` DIV element currently in the document instead of always creating one. - MochiKit.Base now has operator.mul - MochiKit.DOM.formContents correctly handles unchecked checkboxes that have a custom value attribute - Added new MochiKit.Color constructors fromComputedStyle and fromText - MochiKit.DOM.setNodeAttribute should work now - MochiKit.DOM now has a workaround for an IE bug when setting the style property to a string - MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the name and for properties - MochiKit.DOM.scrapeText now walks the DOM tree in-order - MochiKit.LoggingPane now sanitizes the window name to work around IE bug - MochiKit.DOM now translates usemap to useMap to work around IE bug - MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks - Added new MochiKit.DOM documentation on element visibility - New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}]) for determining the position of an element in the document - Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG 2005-11-14 v1.1 - Fixed a bug in numberFormatter with large numbers - Massively overhauled documentation - Fast-path for primitives in MochiKit.Base.compare - New groupby and groupby_as_array in MochiKit.Iter - Added iterator factory adapter for objects that implement iterateNext() - Fixed isoTimestamp to handle timestamps with time zone correctly - Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP, LEGEND, FIELDSET - New MochiKit.DOM formContents and enhancement to queryString to support it - Updated view_source example to use dp.SyntaxHighlighter 1.3.0 - MochiKit.LoggingPane now uses named windows based on the URL so that a given URL will get the same LoggingPane window after a reload (at the same position, etc.) - MochiKit.DOM now has currentWindow() and currentDocument() context variables that are set with withWindow() and withDocument(). These context variables affect all MochiKit.DOM functionality (getElement, createDOM, etc.) - MochiKit.Base.items will now catch and ignore exceptions for properties that are enumerable but not accessible (e.g. permission denied) - MochiKit.Async.Deferred's addCallback/addErrback/addBoth now accept additional arguments that are used to create a partially applied function. This differs from Twisted in that the callback/errback result becomes the *last* argument, not the first when this feature is used. - MochiKit.Async's doSimpleXMLHttpRequest will now accept additional arguments which are used to create a GET query string - Did some refactoring to reduce the footprint of MochiKit by a few kilobytes - escapeHTML to longer escapes ' (apos) and now uses String.replace instead of iterating over every char. - Added DeferredLock to Async - Renamed getElementsComputedStyle to computedStyle and moved it from MochiKit.Visual to MochiKit.DOM - Moved all color support out of MochiKit.Visual and into MochiKit.Color - Fixed range() to accept a negative step - New alias to MochiKit.swapDOM called removeElement - New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets an attribute on a node without raising, roughly equivalent to: updateNodeAttributes(node, {attr: value}) - New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of a node's attribute or returns null without raising - Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack directly (addLoadEvent did not leak, since it clears the handler) 2005-10-24 v1.0 - New interpreter example that shows usage of MochiKit.DOM to make an interactive JavaScript interpreter - New MochiKit.LoggingPane for use with the MochiKit.Logging debuggingBookmarklet, with logging_pane example to show its usage - New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async in order to provide a live regular expression matching tool - Added advanced number formatting capabilities to MochiKit.Format: numberFormatter(pattern, placeholder="", locale="default") and formatLocale(locale="default") - Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate. - Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE - Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision) to MochiKit.Format - MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically isoTimestamp(isoString) will convert them to Date objects, and toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC - Fixed missing errback for sendXMLHttpRequest when the server does not respond - Fixed infinite recusion bug when using roundClass("DIV", ...) - Fixed a bug in MochiKit.Async wait (and callLater) that prevented them from being cancelled properly - Workaround in MochiKit.Base bind (and partial) for functions that don't have an apply method, such as alert - Reliably return null from the string parsing/manipulation functions if the input can't be coerced to a string (s + "") or the input makes no sense; e.g. isoTimestamp(null) and isoTimestamp("") return null 2005-10-08 v0.90 - Fixed ISO compliance with toISODate - Added missing operator.sub - Placated Mozilla's strict warnings a bit - Added JSON serialization and unserialization support to MochiKit.Base: serializeJSON, evalJSON, registerJSON. This is very similar to the repr API. - Fixed a bug in the script loader that failed in some scenarios when a script tag did not have a "src" attribute (thanks Ian!) - Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA, P, FORM - Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode and parseQueryString, when available. 2005-08-12 v0.80 - Source highlighting in all examples, moved to a view-source example - Added some experimental syntax highlighting for the Rounded Corners example, via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib - Use an indirect binding for the logger conveniences, so that the global logger could be replaced by setting MochiKit.Logger.logger to something else (though an observer is probably a better choice). - Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent, which will be looked up with getElement - Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of node.parentNode) - Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success - Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues - Possible workaround for Safari issue with swapDOM, where it would get confused because two elements were in the DOM at the same time with the same id - Added missing THEAD convenience function to MochiKit.DOM - Added lstrip, rstrip, strip to MochiKit.Format - Added updateNodeAttributes, appendChildNodes, replaceChildNodes to MochiKit.DOM - MochiKit.Iter.iextend now has a fast-path for array-like objects - Added HSV color space support to MochiKit.Visual - Fixed a bug in the sortable_tables example, it now converts types correctly - Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global scope 2005-08-04 v0.70 - New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and a little TAL-ish DOM templating attribute language. - sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer ignore requests with status == 0, which seems to happen for cached or local requests - Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh. - Changed scrapeText API to return a string by default. This is API-breaking! It was dumb to have the default return value be the form you almost never want. Sorry. - Added special form to swapDOM(dest, src). If src is null, dest is removed (where previously you'd likely get a DOM exception). - Added three new functions to MochiKit.Base for dealing with URL query strings: urlEncode, queryString, parseQueryString - MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name starts with "on" (e.g. "onclick"). If v is a string, it will set it to new Function(v). - Another workaround for Internet "worst browser ever" Explorer's setAttribute usage in MochiKit.DOM.createDOM (checked -> defaultChecked). - Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM - Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller now! 2005-07-29 v0.60 - Beefed up the MochiKit.DOM test suite - Fixed return value for MochiKit.DOM.swapElementClass, could return false unexpectedly before - Added an optional "parent" argument to MochiKit.DOM.getElementsByTagAndClassName - Added a "packed" version in packed/MochiKit/MochiKit.js - Changed build script to rewrite the URLs in tests to account for the JSAN-required reorganization - MochiKit.Compat to potentially work around IE 5.5 issues (5.0 still not supported). Test.Simple doesn't seem to work there, though. - Several minor documentation corrections 2005-07-27 v0.50 - Initial Release MochiKit-1.4.2/doc/rst/MochiKit/DOM.rst0000660000175000017500000010357011102662076016541 0ustar scottscott.. title:: MochiKit.DOM - painless DOM manipulation API Name ==== MochiKit.DOM - painless DOM manipulation API Synopsis ======== :: var rows = [ ["dataA1", "dataA2", "dataA3"], ["dataB1", "dataB2", "dataB3"] ]; row_display = function (row) { return TR(null, map(partial(TD, null), row)); } var newTable = TABLE({'class': 'prettytable'}, THEAD(null, row_display(["head1", "head2", "head3"])), TFOOT(null, row_display(["foot1", "foot2", "foot3"])), TBODY(null, map(row_display, rows))); // put that in your document.createElement and smoke it! swapDOM(oldTable, newTable); Description =========== As you probably know, the DOM APIs are some of the most painful Java-inspired APIs you'll run across from a highly dynamic language. Don't worry about that though, because they provide a reasonable basis to build something that sucks a lot less. MochiKit.DOM takes much of its inspiration from Nevow's [1]_ stan [2]_. This means you choose a tag, give it some attributes, then stuff it full of *whatever objects you want*. MochiKit.DOM isn't stupid, it knows that a string should be a text node, and that you want functions to be called, and that ``Array``-like objects should be expanded, and stupid ``null`` values should be skipped. Hell, it will let you return strings from functions, and use iterators from :mochiref:`MochiKit.Iter`. If that's not enough, just teach it new tricks with :mochiref:`registerDOMConverter`. If you have never used an API like this for creating DOM elements, you've been wasting your damn time. Get with it! Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.Style` (optional since MochiKit 1.4 for backwards-compatibility) - :mochiref:`MochiKit.Iter` (optional since MochiKit 1.4) Overview ======== DOM Coercion Rules ------------------ In order of precedence, :mochiref:`createDOM` coerces given arguments to DOM nodes using the following rules: 1. Functions are called with a ``this`` and first argument of the parent node and their return value is subject to the following rules (even this one). 2. ``undefined`` and ``null`` are ignored. 3. If :mochiref:`MochiKit.Iter` is loaded, iterables are flattened (as if they were passed in-line as nodes) and each return value is subject to these rules. 4. Values that look like DOM nodes (objects with a ``.nodeType > 0``) are ``.appendChild``'ed to the created DOM fragment. 5. Strings are wrapped up with ``document.createTextNode`` 6. Objects that have a ``.dom(node)`` or ``.__dom__(node)`` method are called with the parent node and their result is coerced using these rules. (MochiKit 1.4+). 7. Objects that are not strings are run through the ``domConverters`` :mochiref:`MochiKit.Base.AdapterRegistry` (see :mochiref:`registerDOMConverter`). The adapted value is subject to these same rules (e.g. if the adapter returns a string, it will be coerced to a text node). 8. If no adapter is available, ``.toString()`` is used to create a text node. Creating DOM Element Trees -------------------------- :mochiref:`createDOM` provides you with an excellent facility for creating DOM trees that is easy on the wrists. One of the best ways to understand how to use it is to take a look at an example:: var rows = [ ["dataA1", "dataA2", "dataA3"], ["dataB1", "dataB2", "dataB3"] ]; row_display = function (row) { return TR(null, map(partial(TD, null), row)); } var newTable = TABLE({'class': 'prettytable'}, THEAD(null, row_display(["head1", "head2", "head3"])), TFOOT(null, row_display(["foot1", "foot2", "foot3"])), TBODY(null, map(row_display, rows))); This will create a table with the following visual layout (if it were inserted into the document DOM): +--------+--------+--------+ | head1 | head2 | head3 | +========+========+========+ | dataA1 | dataA2 | dataA3 | +--------+--------+--------+ | dataB1 | dataB2 | dataB3 | +--------+--------+--------+ | foot1 | foot2 | foot3 | +--------+--------+--------+ Corresponding to the following HTML::
head1 head2 head3
foot1 foot2 foot3
dataA1 dataA2 dataA3
dataB1 dataB2 dataB3
DOM Context ----------- In order to prevent having to pass a ``window`` and/or ``document`` variable to every MochiKit.DOM function (e.g. when working with a child window), MochiKit.DOM maintains a context variable for each of them. They are managed with the :mochiref:`withWindow` and :mochiref:`withDocument` functions, and can be acquired with :mochiref:`currentWindow()` and :mochiref:`currentDocument()` For example, if you are creating DOM nodes in a child window, you could do something like this:: withWindow(child, function () { var doc = currentDocument(); appendChildNodes(doc.body, H1(null, "This is in the child!")); }); Note that :mochiref:`withWindow(win, ...)` also implies :mochiref:`withDocument(win.document, ...)`. DOM Gotchas ----------- Performance Tradeoff: DOM is much easier to get correct and more flexible than working directly with markup as strings. Modifying ``innerHTML`` is still the fastest way to make document changes. Internet Explorer: Internet Explorer's DOM implementation is quite poor in comparison to the other popular implementations. In order to avoid memory leaks due to circular references, you should use :mochiref:`MochiKit.Signal.connect` for all of your event handling needs. Additionally, when creating tables with DOM, it is required to use a ``TBODY`` tag (see `Creating DOM Element Trees`_ for an example of this). API Reference ============= Functions --------- :mochidef:`$(id[, ...])`: An alias for :mochiref:`getElement(id[, ...])` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`addElementClass(element, className)`: Ensure that the given ``element`` has ``className`` set as part of its class attribute. This will not disturb other class names. ``element`` is looked up with :mochiref:`getElement`, so string identifiers are also acceptable. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`addLoadEvent(func)`: Note that :mochiref:`addLoadEvent` can not be used in combination with :mochiref:`MochiKit.Signal` if the ``onload`` event is connected. Once an event is connected with :mochiref:`MochiKit.Signal`, no other APIs may be used for that same event. This will stack ``window.onload`` functions on top of each other. Each function added will be called after ``onload`` in the order that they were added. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`addToCallStack(target, path, func[, once])`: Note that :mochiref:`addToCallStack` is not compatible with :mochiref:`MochiKit.Signal`. Once an event is connected with :mochiref:`MochiKit.Signal`, no other APIs may be used for that same event. Set the property ``path`` of ``target`` to a function that calls the existing function at that property (if any), then calls ``func``. If ``target[path]()`` returns exactly ``false``, then ``func`` will not be called. If ``once`` is ``true``, then ``target[path]`` is set to ``null`` after the function call stack has completed. If called several times for the same ``target[path]``, it will create a stack of functions (instead of just a pair). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`appendChildNodes(node[, childNode[, ...]])`: Append children to a DOM element using the `DOM Coercion Rules`_. ``node``: A reference to the DOM element to add children to (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``childNode``...: All additional arguments, if any, will be coerced into DOM nodes that are appended as children using the `DOM Coercion Rules`_. *returns*: The given DOM element *Availability*: Available in MochiKit 1.3.1+ :mochidef:`insertSiblingNodesBefore(node[, siblingNode[, ...]])`: Insert children into the DOM structure using the `DOM Coercion Rules`_. ``node``: A reference to the DOM element you want to insert children before (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``siblingNode``...: All additional arguments, if any, will be coerced into DOM nodes that are inserted as siblings using the `DOM Coercion Rules`_. *returns*: The parent of the given DOM element *Availability*: Available in MochiKit 1.4+ :mochidef:`insertSiblingNodesAfter(node[, siblingNode[, ...]])`: Insert children into the DOM structure using the `DOM Coercion Rules`_. ``node``: A reference to the DOM element you want to insert children after (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``siblingNode``...: All additional arguments, if any, will be coerced into DOM nodes that are inserted as siblings using the `DOM Coercion Rules`_. *returns*: The parent of the given DOM element *Availability*: Available in MochiKit 1.4+ :mochidef:`createDOM(name[, attrs[, node[, ...]]])`: Create a DOM fragment in a really convenient manner, much like Nevow`s [1]_ stan [2]_. Partially applied versions of this function for common tags are available as aliases: - ``A`` - ``BUTTON`` - ``BR`` - ``CANVAS`` - ``DD`` - ``DIV`` - ``DL`` - ``DT`` - ``FIELDSET`` - ``FORM`` - ``H1`` - ``H2`` - ``H3`` - ``H4`` - ``H5`` - ``H6`` - ``HR`` - ``IMG`` - ``INPUT`` - ``LABEL`` - ``LEGEND`` - ``LI`` - ``OL`` - ``OPTGROUP`` - ``OPTION`` - ``P`` - ``PRE`` - ``SELECT`` - ``SPAN`` - ``STRONG`` - ``TABLE`` - ``TBODY`` - ``TD`` - ``TEXTAREA`` - ``TFOOT`` - ``TH`` - ``THEAD`` - ``TR`` - ``TT`` - ``UL`` See `Creating DOM Element Trees`_ for a comprehensive example. ``name``: The kind of fragment to create (e.g. 'span'), such as you would pass to ``document.createElement``. ``attrs``: An object whose properties will be used as the attributes (e.g. ``{'style': 'display:block'}``), or ``null`` if no attributes need to be set. See :mochiref:`updateNodeAttributes` for more information. For convenience, if ``attrs`` is a string, ``null`` is used and the string will be considered the first ``node``. ``node``...: All additional arguments, if any, will be coerced into DOM nodes that are appended as children using the `DOM Coercion Rules`_. *returns*: A DOM element *Availability*: Available in MochiKit 1.3.1+ :mochidef:`createDOMFunc(tag[, attrs[, node[, ...]]])`: Convenience function to create a partially applied createDOM function. You'd want to use this if you add additional convenience functions for creating tags, or if you find yourself creating a lot of tags with a bunch of the same attributes or contents. See :mochiref:`createDOM` for more detailed descriptions of the arguments. ``tag``: The name of the tag ``attrs``: Optionally specify the attributes to apply ``node``...: Optionally specify any children nodes it should have *returns*: function that takes additional arguments and calls :mochiref:`createDOM` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`currentDocument()`: Return the current ``document`` `DOM Context`_. This will always be the same as the global ``document`` unless :mochiref:`withDocument` or :mochiref:`withWindow` is currently executing. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`currentWindow()`: Return the current ``window`` `DOM Context`_. This will always be the same as the global ``window`` unless :mochiref:`withWindow` is currently executing. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`emitHTML(dom[, lst])`: Convert a DOM tree to an ``Array`` of HTML string fragments. This should be used for debugging/testing purposes only. The DOM property ``innerHTML`` or ``cloneNode(true)`` method should be used for most purposes. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`escapeHTML(s)`: Make a string safe for HTML, converting the usual suspects (``<``, ``>``, ``"``, ``&``) to their HTML character entity equivalents. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`focusOnLoad(element)`: Note that :mochiref:`focusOnLoad` can not be used in combination with :mochiref:`MochiKit.Signal` if the ``onload`` event is connected. Once an event is connected with :mochiref:`MochiKit.Signal`, no other APIs may be used for that same event. This adds an onload event to focus the given element. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`formContents(elem=document.body)`: Search the DOM tree, starting at ``elem``, for any elements with a ``name`` and ``value`` attribute. Return a 2-element ``Array`` of ``names`` and ``values`` suitable for use with :mochiref:`MochiKit.Base.queryString`. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`getElement(id[, ...])`: A small quick little function to encapsulate the ``getElementById`` method. It includes a check to ensure we can use that method. If the id isn't a string, it will be returned as-is. Also available as :mochiref:`$(...)` for convenience and compatibility with other JavaScript frameworks. If multiple arguments are given, an ``Array`` will be returned. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`getElementsByTagAndClassName(tagName, className, parent=document)`: Returns an array of elements in ``parent`` that match the tag name and class name provided. If ``parent`` is a string, it will be looked up with :mochiref:`getElement`. If ``tagName`` is ``null`` or ``"*"``, all elements will be searched for the matching class. If ``className`` is ``null``, all elements matching the provided tag are returned. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`getFirstElementByTagAndClassName(tagName, className, parent=document)`: Return the first element in ``parent`` that matches the tag name and class name provided. If ``parent`` is a string, it will be looked up with :mochiref:`getElement`. If ``tagName`` is ``null`` or ``"*"``, all elements will be searched for the matching class. If ``className`` is ``null``, the first element matching the provided tag will be returned. *Availability*: Available in MochiKit 1.4+ :mochidef:`getFirstParentByTagAndClassName(elem, tagName='*', className=null)`: Returns the first parent of ``elem`` that matches the tag name and class name provided. If ``elem`` is a string, it will be looked up using :mochiref:`getElement`. If ``tagName`` is ``null`` or ``"*"``, all elements will be searched for the matching class. If ``className`` is ``null``, the first element matching the provided tag name will be returned. If no match is found, ``null`` will be returned. *Availability*: Available in MochiKit 1.4+ :mochidef:`getNodeAttribute(node, attr)`: Get the value of the given attribute for a DOM element without ever raising an exception (will return ``null`` on exception). ``node``: A reference to the DOM element to update (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``attr``: The name of the attribute Note that it will do the right thing for IE, so don't do the ``class`` -> ``className`` hack yourself. *returns*: The attribute's value, or ``null`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`hasElementClass(element, className[, ...])`: Return ``true`` if ``className`` is found on the ``element``. ``element`` is looked up with :mochiref:`getElement`, so string identifiers are also acceptable. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`isChildNode(node, maybeParent)`: Determine whether ``node`` is a child node or decendant node of ``maybeParent``. Returns ``true`` if so, and ``false`` if not. A node is considered a child node of itself for the purposes of this function. If either ``node`` or ``maybeParent`` are strings, the related nodes will be looked up with :mochiref:`getElement`. *Availability*: Available in MochiKit 1.4+ :mochidef:`registerDOMConverter(name, check, wrap[, override])`: Register an adapter to convert objects that match ``check(obj, ctx)`` to a DOM element, or something that can be converted to a DOM element (i.e. number, bool, string, function, iterable). *Availability*: Available in MochiKit 1.3.1+ :mochidef:`removeElement(node)`: Remove and return ``node`` from a DOM tree. ``node``: the DOM element (or string id of one) to be removed *returns* The removed element *Availability*: Available in MochiKit 1.3.1+ :mochidef:`removeElementClass(element, className)`: Ensure that the given ``element`` does not have ``className`` set as part of its class attribute. This will not disturb other class names. ``element`` is looked up with :mochiref:`getElement`, so string identifiers are also acceptable. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`removeEmptyTextNodes(node)`: Remove all text node children that contain only whitespace from ``node``. Useful in situations where such empty text nodes can interfere with DOM traversal. ``node``: the DOM element (or string id of one) to remove whitespace child nodes from. *Availability*: Available in MochiKit 1.4+ :mochidef:`replaceChildNodes(node[, childNode[, ...]])`: Remove all children from the given DOM element, then append any given childNodes to it (by calling :mochiref:`appendChildNodes`). ``node``: A reference to the DOM element to add children to (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``childNode``...: All additional arguments, if any, will be coerced into DOM nodes that are appended as children using the `DOM Coercion Rules`_. *returns*: The given DOM element *Availability*: Available in MochiKit 1.3.1+ :mochidef:`scrapeText(node[, asArray=false])`: Walk a DOM tree in-order and scrape all of the text out of it as a ``string``. If ``asArray`` is ``true``, then an ``Array`` will be returned with each individual text node. These two are equivalent:: assert( scrapeText(node) == scrapeText(node, true).join("") ); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`setElementClass(element, className)`: Set the entire class attribute of ``element`` to ``className``. ``element`` is looked up with :mochiref:`getElement`, so string identifiers are also acceptable. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`setNodeAttribute(node, attr, value)`: Set the value of the given attribute for a DOM element without ever raising an exception (will return null on exception). If setting more than one attribute, you should use :mochiref:`updateNodeAttributes`. ``node``: A reference to the DOM element to update (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``attr``: The name of the attribute Note that it will do the right thing for IE, so don't do the ``class`` -> ``className`` hack yourself. Also note that the DOM element object property with the same name will also be set if not already identical to the attribute value. This is needed to compensate for weird attributes that distinguish between the property and attribute values (i.e. the "value" attribute for fields). ``value``: The value of the attribute, may be an object to be merged (e.g. for setting style). *returns*: The given DOM element or ``null`` on failure *Availability*: Available in MochiKit 1.3.1+ :mochidef:`swapDOM(dest, src)`: Replace ``dest`` in a DOM tree with ``src``, returning ``src``. ``dest``: a DOM element (or string id of one) to be replaced ``src``: the DOM element (or string id of one) to replace it with, or ``null`` if ``dest`` is to be removed (replaced with nothing). *returns*: a DOM element (``src``) *Availability*: Available in MochiKit 1.3.1+ :mochidef:`swapElementClass(element, fromClass, toClass)`: If ``fromClass`` is set on ``element``, replace it with ``toClass``. This will not disturb other classes on that element. ``element`` is looked up with :mochiref:`getElement`, so string identifiers are also acceptable. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toggleElementClass(className[, element[, ...]])`: Toggle the presence of a given ``className`` in the class attribute of all given elements. All elements will be looked up with :mochiref:`getElement`, so string identifiers are acceptable. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toHTML(dom)`: Convert a DOM tree to a HTML string using :mochiref:`emitHTML`. This should be used for debugging/testing purposes only. The DOM property ``innerHTML`` or ``cloneNode(true)`` method should be used for most purposes. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`updateNodeAttributes(node, attrs)`: Update the attributes of a DOM element from a given object. ``node``: A reference to the DOM element to update (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``attrs``: An object whose properties will be used to set the attributes (e.g. ``{'class': 'invisible'}``), or ``null`` if no attributes need to be set. If an object is given for the attribute value (e.g. ``{'style': {'display': 'block'}}``) then :mochiref:`MochiKit.Base.updatetree` will be used to set that attribute. Note that it will do the right thing for IE, so don't do the ``class`` -> ``className`` hack yourself, and it deals with setting "on..." event handlers correctly. Also note that the DOM element object property with the same name will also be set if not already identical to the attribute value. This is needed to compensate for weird attributes that distinguish between the property and attribute values (i.e. the "value" attribute for fields). *returns*: The given DOM element *Availability*: Available in MochiKit 1.3.1+ :mochidef:`withWindow(win, func)`: Call ``func`` with the ``window`` `DOM Context`_ set to ``win`` and the ``document`` `DOM Context`_ set to ``win.document``. When ``func()`` returns or throws an error, the `DOM Context`_ will be restored to its previous state. The return value of ``func()`` is returned by this function. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`withDocument(doc, func)`: Call ``func`` with the ``doc`` `DOM Context`_ set to ``doc``. When ``func()`` returns or throws an error, the `DOM Context`_ will be restored to its previous state. The return value of ``func()`` is returned by this function. *Availability*: Available in MochiKit 1.3.1+ Style Functions --------------- These functions were previously available in MochiKit.DOM, but have been moved to :mochiref:`MochiKit.Style` in recent versions. Function aliases remain for backwards compability. :mochidef:`computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS)`: Looks up a CSS property for the given element. The element can be specified as either a string with the element's ID or the element object itself. ``cssProperty``: MochiKit 1.3.1 expects camel case, e.g. ``backgroundColor``. MochiKit 1.4+ expects CSS selector case, e.g. ``background-color``, but will accept camel case for backwards-compatibility. ``mozillaEquivalentCSS``: MochiKit 1.3.1 expects selector case. MochiKit 1.4+ ignores this argument. *Availability*: Available in MochiKit 1.3.1, deprecated in favor of :mochiref:`MochiKit.Style.getStyle` in 1.4+ :mochidef:`elementDimensions(element)`: Return the absolute pixel width and height (including padding and border, but not margins) of ``element`` as an object with ``w`` and ``h`` properties, or ``undefined`` if ``element`` is not in the document. ``element`` may be specified as a string to be looked up with :mochiref:`getElement`, a DOM element, or trivially as an object with ``w`` and/or ``h`` properties. *Availability*: Available in MochiKit 1.3.1, deprecated in favor of :mochiref:`MochiKit.Style.getElementDimensions` in 1.4+ :mochidef:`elementPosition(element[, relativeTo={x: 0, y: 0}])`: Return the absolute pixel position of ``element`` in the document as an object with ``x`` and ``y`` properties, or ``undefined`` if ``element`` is not in the document. ``element`` may be specified as a string to be looked up with :mochiref:`getElement`, a DOM element, or trivially as an object with ``x`` and/or ``y`` properties. If ``relativeTo`` is given, then its coordinates are subtracted from the absolute position of ``element``, e.g.:: var elemPos = elementPosition(elem); var anotherElemPos = elementPosition(anotherElem); var relPos = elementPosition(elem, anotherElem); assert( relPos.x == (elemPos.x - anotherElemPos.x) ); assert( relPos.y == (elemPos.y - anotherElemPos.y) ); ``relativeTo`` may be specified as a string to be looked up with :mochiref:`getElement`, a DOM element, or trivially as an object with ``x`` and/or ``y`` properties. *Availability*: Available in MochiKit 1.3.1, deprecated in favor of :mochiref:`MochiKit.Style.getElementPosition` in 1.4+ :mochidef:`getViewportDimensions()`: Return the pixel width and height of the viewport as an object with ``w`` and ``h`` properties. ``element`` is looked up with :mochiref:`getElement`, so string identifiers are also acceptable. *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.getViewportDimensions` in 1.4+ :mochidef:`hideElement(element, ...)`: Partial form of :mochiref:`setDisplayForElement`, specifically:: partial(setDisplayForElement, "none") For information about the caveats of using a ``style.display`` based show/hide mechanism, and a CSS based alternative, see `Element Visibility`_. .. _`Element Visibility`: Style.html#element-visibility *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.hideElement` in 1.4+ :mochidef:`makeClipping(element)`: Ensure that ``element.style.overflow = 'hidden'``. If ``element`` is a string, then it will be looked up with :mochiref:`getElement`. Returns the original values of ``overflow``, ``overflow-y`` and ``overflow-y`` so that they may be restored with :mochiref:`undoClipping(element, overflow)`. *Availability*: Available in MochiKit 1.4+, moved to :mochiref:`MochiKit.Style.makeClipping` in 1.4.1+ :mochidef:`makePositioned(element)`: Ensure that ``element.style.position`` is set to ``"relative"`` if it is not set or is ``"static"``. If ``element`` is a string, then it will be looked up with :mochiref:`getElement`. *Availability*: Available in MochiKit 1.4+, moved to :mochiref:`MochiKit.Style.makePositioned` in 1.4.1+ :mochidef:`setElementDimensions(element, dimensions[, units='px'])`: Sets the dimensions of ``element`` in the document from an object with ``w`` and ``h`` properties. ``node``: A reference to the DOM element to update (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``dimensions``: An object with ``w`` and ``h`` properties ``units``: Optionally set the units to use, default is ``px`` *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.setElementDimensions` in 1.4+ :mochidef:`setElementPosition(element, position[, units='px'])`: Sets the absolute position of ``element`` in the document from an object with ``x`` and ``y`` properties. ``node``: A reference to the DOM element to update (if a string is given, :mochiref:`getElement(node)` will be used to locate the node) ``position``: An object with ``x`` and ``y`` properties ``units``: Optionally set the units to use, default is ``px`` *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.setElementPosition` in 1.4+ :mochidef:`setDisplayForElement(display, element[, ...])`: Change the ``style.display`` for the given element(s). Usually used as the partial forms: - :mochiref:`showElement(element, ...)` - :mochiref:`hideElement(element, ...)` Elements are looked up with :mochiref:`getElement`, so string identifiers are acceptable. For information about the caveats of using a ``style.display`` based show/hide mechanism, and a CSS based alternative, see `Element Visibility`_. *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.setDisplayForElement` in 1.4+ :mochidef:`setOpacity(element, opacity)`: Sets ``opacity`` for ``element``. Valid ``opacity`` values range from 0 (invisible) to 1 (opaque). ``element`` is looked up with :mochiref:`getElement`, so string identifiers are also acceptable. *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.setOpacity` in 1.4+ :mochidef:`showElement(element, ...)`: Partial form of :mochiref:`setDisplayForElement`, specifically:: partial(setDisplayForElement, "block") For information about the caveats of using a ``style.display`` based show/hide mechanism, and a CSS based alternative, see `Element Visibility`_. *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.showElement` in 1.4+ :mochidef:`undoClipping(element, overflow)`: Restore the setting of ``element.style.overflow`` set by :mochiref:`makeClipping(element)`. If ``element`` is a string, then it will be looked up with :mochiref:`getElement`. *Availability*: Available in MochiKit 1.4+, moved to :mochiref:`MochiKit.Style.undoClipping` in 1.4.1+ :mochidef:`undoPositioned(element)`: Restore the setting of ``element.style.position`` set by :mochiref:`makePositioned(element)`. If ``element`` is a string, then it will be looked up with :mochiref:`getElement`. *Availability*: Available in MochiKit 1.4+, moved to :mochiref:`MochiKit.Style.undoPositioned` in 1.4.1+ Style Objects ------------- These objects are available in MochiKit 1.3.1, but have been moved to :mochiref:`MochiKit.Style` in 1.4+. :mochidef:`Coordinates(x, y)`: Constructs an object with ``x`` and ``y`` properties. ``obj.toString()`` returns something like ``{x: 0, y: 42}`` for debugging. *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.Coordinates` in 1.4+ :mochidef:`Dimensions(w, h)`: Constructs an object with ``w`` and ``h`` properties. ``obj.toString()`` returns something like ``{w: 0, h: 42}`` for debugging. *Availability*: Available in MochiKit 1.3.1, moved to :mochiref:`MochiKit.Style.Dimensions` in 1.4+ See Also ======== .. [1] Nevow, a web application construction kit for Python: http://divmod.org/trac/wiki/DivmodNevow .. [2] nevow.stan is a domain specific language for Python (read as "crazy getitem/call overloading abuse") that Donovan and I schemed up at PyCon 2003 at this super ninja Python/C++ programmer's (David Abrahams) hotel room. Donovan later inflicted this upon the masses in Nevow. Check out the Nevow Guide for some examples: http://divmod.org/trac/wiki/DivmodNevow Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Iter.rst0000660000175000017500000002550711102215564017024 0ustar scottscott.. title:: MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy Name ==== MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy Synopsis ======== :: theSum = sum(takewhile( partial(operator.gt, 10), imap( partial(operator.mul, 2), count() ) ) )); assert( theSum == (0 + 0 + 2 + 4 + 6 + 8) ); Description =========== All of the functional programming missing from :mochiref:`MochiKit.Base` lives here. The functionality in this module is largely inspired by Python's iteration protocol [1]_, and the itertools module [2]_. MochiKit.Iter defines a standard way to iterate over anything, that you can extend with :mochiref:`registerIteratorFactory`, or by implementing the ``.iter()`` or ``.__iterator__()`` (in MochiKit 1.4+) protocol. Iterators are lazy, so it can potentially be cheaper to build a filter chain of iterators than to build lots of intermediate arrays. Especially when the data set is very large, but the result is not. Dependencies ============ - :mochiref:`MochiKit.Base` Overview ======== Iteration for JavaScript ------------------------ The best overview right now is in my Iteration for JavaScript [3]_ blog entry. This information will migrate here eventually. API Reference ============= Errors ------ :mochidef:`StopIteration`: The singleton :mochiref:`MochiKit.Base.NamedError` that signifies the end of an iterator *Availability*: Available in MochiKit 1.3.1+ Functions --------- :mochidef:`applymap(fun, seq[, self])`: ``applymap(fun, seq)`` --> fun.apply(self, seq0), fun.apply(self, seq1), ... *Availability*: Available in MochiKit 1.3.1+ :mochidef:`chain(p, q[, ...])`: ``chain(p, q, ...)`` --> p0, p1, ... plast, q0, q1, ... *Availability*: Available in MochiKit 1.3.1+ :mochidef:`count(n=0)`: ``count(n=0)`` --> n, n + 1, n + 2, ... *Availability*: Available in MochiKit 1.3.1+ :mochidef:`cycle(p)`: ``cycle(p)`` --> p0, p1, ... plast, p0, p1, ... *Availability*: Available in MochiKit 1.3.1+ :mochidef:`dropwhile(pred, seq)`: ``dropwhile(pred, seq)`` --> seq[n], seq[n + 1], starting when pred(seq[n]) fails *Availability*: Available in MochiKit 1.3.1+ :mochidef:`every(iterable, func)`: Return ``true`` if ``func(item)`` is ``true`` for every item in ``iterable``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`exhaust(iterable)`: Exhausts an iterable without saving the results anywhere, like :mochiref:`list(iterable)` when you don't care what the output is. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`forEach(iterable, func[, self])`: Call ``func`` for each item in ``iterable``, and don't save the results. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`groupby(iterable[, keyfunc])`: Make an iterator that returns consecutive keys and groups from the iterable. The key is a function computing a key value for each element. If not specified or is None, key defaults to an identity function and returns the element unchanged. Generally, the iterable needs to already be sorted on the same key function. The returned group is itself an iterator that shares the underlying iterable with :mochiref:`groupby()`. Because the source is shared, when the groupby object is advanced, the previous group is no longer visible. So, if that data is needed later, it should be stored as an array:: var groups = []; var uniquekeys = []; forEach(groupby(data, keyfunc), function (key_group) { groups.push(list(key_group[1])); uniquekeys.push(key_group[0]); }); As a convenience, :mochiref:`groupby_as_array()` is provided to suit the above use case. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`groupby_as_array(iterable[, keyfunc])`: Perform the same task as :mochiref:`groupby()`, except return an array of arrays instead of an iterator of iterators. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`iextend(lst, iterable)`: Just like :mochiref:`list(iterable)`, except it pushes results on ``lst`` rather than creating a new one. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`ifilter(pred, seq)`: ``ifilter(pred, seq)`` --> elements of seq where ``pred(elem)`` is ``true`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`ifilterfalse(pred, seq)`: ``ifilterfalse(pred, seq)`` --> elements of seq where ``pred(elem)`` is ``false`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`imap(fun, p, q[, ...])`: ``imap(fun, p, q, ...)`` --> fun(p0, q0, ...), fun(p1, q1, ...), ... *Availability*: Available in MochiKit 1.3.1+ :mochidef:`islice(seq, [start,] stop[, step])`: ``islice(seq, [start,] stop[, step])`` --> elements from seq[start:stop:step] (in Python slice syntax) *Availability*: Available in MochiKit 1.3.1+ :mochidef:`iter(iterable[, sentinel])`: Convert the given argument to an iterator (object implementing ``.next()``). 1. If ``iterable`` is an iterator (implements ``.next()``), then it will be returned as-is. 2. If ``iterable`` is an iterator factory (implements ``.iter()``), then the result of ``iterable.iter()`` will be returned. 3. If ``iterable`` is a JavaScript 1.7 iterator factory (implements ``.__iterable__()``), then the result of ``iterable.__iterable__()`` will be returned (MochiKit 1.4+). 4. Otherwise, the iterator factory :mochiref:`MochiKit.Base.AdapterRegistry` is used to find a match. 5. If no factory is found, it will throw ``TypeError`` Built-in iterator factories are present for Array-like objects, and objects that implement the ``iterateNext`` protocol (e.g. the result of Mozilla's ``document.evaluate``). When used directly, using an iterator should look like this:: var it = iter(iterable); try { while (var o = it.next()) { // use o } } catch (e) { if (e != StopIteration) { throw e; } // pass } This is ugly, so you should use the higher order functions to work with iterators whenever possible. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`izip(p, q[, ...])`: ``izip(p, q, ...)`` --> [p0, q0, ...], [p1, q1, ...], ... *Availability*: Available in MochiKit 1.3.1+ :mochidef:`list(iterable)`: Convert ``iterable`` to a new ``Array`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`next(iterator)`: Return ``iterator.next()`` *Availability*: Available in MochiKit 1.3.1+ :mochidef:`range([start,] stop[, step])`: Return an iterator containing an arithmetic progression of integers. ``range(i, j)`` returns :mochiref:`iter([i, i + 1, i + 2, ..., j - 1])` ``start`` (!) defaults to ``0``. When ``step`` is given, it specifies the increment (or decrement). The end point is omitted! For example, ``range(4)`` returns :mochiref:`iter([0, 1, 2, 3])`. This iterates over exactly the valid indexes for an array of 4 elements. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`reduce(fn, iterable[, initial])`: Apply ``fn(a, b)`` cumulatively to the items of an iterable from left to right, so as to reduce the iterable to a single value. For example:: reduce(function (a, b) { return a + b; }, [1, 2, 3, 4, 5]) calculates:: ((((1 + 2) + 3) + 4) + 5). If initial is given, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty. Note that the above example could be written more clearly as:: reduce(operator.add, [1, 2, 3, 4, 5]) Or even simpler:: sum([1, 2, 3, 4, 5]) *Availability*: Available in MochiKit 1.3.1+ :mochidef:`registerIteratorFactory(name, check, iterfactory[, override])`: Register an iterator factory for use with the iter function. ``check`` is a ``function(a)`` that returns ``true`` if ``a`` can be converted into an iterator with ``iterfactory``. ``iterfactory`` is a ``function(a)`` that returns an object with a ``.next()`` method that returns the next value in the sequence. ``iterfactory`` is guaranteed to only be called if ``check(a)`` returns a true value. If ``override`` is ``true``, then it will be made the highest precedence iterator factory. Otherwise, the lowest. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`repeat(elem[, n])`: ``repeat(elem, [,n])`` --> elem, elem, elem, ... endlessly or up to n times *Availability*: Available in MochiKit 1.3.1+ :mochidef:`reversed(iterable)`: Return a reversed array from iterable. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`some(iterable, func)`: Return ``true`` if ``func(item)`` is ``true`` for at least one item in ``iterable``. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`sorted(iterable[, cmp])`: Return a sorted array from iterable. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`sum(iterable, start=0)`: Returns the sum of a sequence of numbers plus the value of parameter ``start`` (with a default of 0). When the sequence is empty, returns start. Equivalent to:: reduce(operator.add, iterable, start); *Availability*: Available in MochiKit 1.3.1+ :mochidef:`takewhile(pred, seq)`: ``takewhile(pred, seq)`` --> seq[0], seq[1], ... until pred(seq[n]) fails *Availability*: Available in MochiKit 1.3.1+ :mochidef:`tee(iterable, n=2)`: ``tee(it, n=2)`` --> [it1, it2, it3, ... itn] splits one iterator into n *Availability*: Available in MochiKit 1.3.1+ See Also ======== .. [1] The iteration protocol is described in PEP 234 - Iterators: http://www.python.org/peps/pep-0234.html .. [2] Python's itertools module: http://docs.python.org/lib/module-itertools.html .. [3] Iteration in JavaScript: http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/ Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/LoggingPane.rst0000660000175000017500000000643711102215564020314 0ustar scottscott.. title:: MochiKit.LoggingPane - Interactive MochiKit.Logging pane Name ==== MochiKit.LoggingPane - Interactive MochiKit.Logging pane Synopsis ======== :: // open a pop-up window createLoggingPane() // use a div at the bottom of the document createLoggingPane(true); Description =========== MochiKit.Logging does not have any browser dependencies and is completely unobtrusive. MochiKit.LoggingPane is a browser-based colored viewing pane for your :mochiref:`MochiKit.Logging` output that can be used as a pop-up or inline. It also allows for regex and level filtering! MochiKit.LoggingPane is used as the default :mochiref:`MochiKit.Logging.debuggingBookmarklet()` if it is loaded. Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.Logging` API Reference ============= Constructors ------------ :mochidef:`LoggingPane(inline=false, logger=MochiKit.Logging.logger)`: A listener for a :mochiref:`MochiKit.Logging` logger with an interactive DOM representation. If ``inline`` is ``true``, then the ``LoggingPane`` will be a ``DIV`` at the bottom of the document. Otherwise, it will be in a pop-up window with a name based on the calling page's URL. If there is an element in the document with an id of ``_MochiKit_LoggingPane``, it will be used instead of appending a new ``DIV`` to the body. ``logger`` is the reference to the :mochiref:`MochiKit.Logging.Logger` to listen to. If not specified, the global default logger is used. Properties: ``win``: Reference to the pop-up window (``undefined`` if ``inline``) ``inline``: ``true`` if the ``LoggingPane`` is inline ``colorTable``: An object with property->value mappings for each log level and its color. May also be mutated on ``LoggingPane.prototype`` to affect all instances. For example:: MochiKit.LoggingPane.LoggingPane.prototype.colorTable = { DEBUG: "green", INFO: "black", WARNING: "blue", ERROR: "red", FATAL: "darkred" }; *Availability*: Available in MochiKit 1.3.1+ :mochidef:`LoggingPane.prototype.closePane()`: Close the :mochiref:`LoggingPane` (close the child window, or remove the ``_MochiKit_LoggingPane`` ``DIV`` from the document). *Availability*: Available in MochiKit 1.3.1+ Functions --------- :mochidef:`createLoggingPane(inline=false)`: Create or return an existing :mochiref:`LoggingPane` for this document with the given inline setting. This is preferred over using :mochiref:`LoggingPane` directly, as only one :mochiref:`LoggingPane` should be present in a given document. *Availability*: Available in MochiKit 1.3.1+ Authors ======= - Bob Ippolito Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/rst/MochiKit/Visual.rst0000660000175000017500000006735711102215564017375 0ustar scottscott.. title:: MochiKit.Visual - visual effects Name ==== MochiKit.Visual - visual effects Synopsis ======== :: // round the corners of all h1 elements roundClass("h1", null); // round the top left corner of the element with the id "title" roundElement("title", {corners: "tl"}); // Add an fade effect to an element fade('myelement'); Description =========== MochiKit.Visual provides visual effects and animations for HTML elements. Dependencies ============ - :mochiref:`MochiKit.Base` - :mochiref:`MochiKit.Iter` - :mochiref:`MochiKit.DOM` - :mochiref:`MochiKit.Color` - :mochiref:`MochiKit.Position` Overview ======== MochiKit.Visual provides different visual effects: rounded corners and animations for your HTML elements. Rounded corners are created completely through CSS manipulations and require no external images or style sheets. This implementation was adapted from Rico_. Dynamic effects are ported from Scriptaculous_. .. _Rico: http://www.openrico.org .. _Scriptaculous: http://script.aculo.us Animations & Effects -------------------- Dynamic or animated effects are managed by a basic looping service (see :mochiref:`Base`). The effect looping is controlled by timers that are invoked at regular and short intervals while the effect is executing. The base looping service takes the current system time into consideration, automatically skipping effect steps on execution delays. The effect classes need only handle dynamic updates based on a floating-point number between ``0.0`` and ``1.0`` (the effect position). This effect position may also be manipulated by :mochiref:`Transitions` to provide non-linear updates, which may further enhance the visual effect. The effect timer and transitions can be controlled through a set of :mochiref:`DefaultOptions` that are available for all effect classes. The Effects Queue ----------------- When you create effects based on user input (mouse clicks for example), it can create conflicts between the effects if multiple effects are running at the same time. To manage this problem, the Queue mechanism has been introduced: it's responsible for running the effects as you desired. By default, you have one Queue called ``'global'``, and the effects run in ``'parallel'`` (see :mochiref:`DefaultOptions`). Every effect has a ``queue`` option to customize this. Its value can be a string, thereby using the ``global`` scope: - `front`: the effect will be run before any other non-started effect; - `end`: the effect will be run when all other effects have finished; - `break`: every other effect is immediately finalized when the the effect start; - `parallel`: the effect runs in parallel with other effects. But you have even more control if you use an object with the following property keys: - `position` takes one of the values listed above; - `scope` contains the queue name. If it's ``"global"`` the effect will use the default queue, otherwise you can define your own queue name. For example, if you add an effect on a specified element, you may use the element id as scope; - `limit` defines how many effects can be stored in the queue at a single time. If an effect is added when the limit has been reached, it will never be run (it's lost). API Reference ============= Functions --------- :mochidef:`roundClass(tagName[, className[, options]])`: Rounds all of the elements that match the ``tagName`` and ``className`` specifiers, using the options provided. ``tagName`` or ``className`` can be ``null`` to match all tags or classes. Regarding the ``options``, see the :mochiref:`roundElement` function. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`roundElement(element[, options])`: Immediately round the corners of the specified ``element``. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: The ``options`` mapping has the following defaults: ========= ================= corners ``"all"`` color ``"fromElement"`` bgColor ``"fromParent"`` blend ``true`` border ``false`` compact ``false`` ========= ================= The ``options`` parameters can have following values: corners: Specifies which corners of the element should be rounded. Choices are: - all - top - bottom - tl (top left) - bl (bottom left) - tr (top right) - br (bottom right) Example: ``"tl br"``: top-left and bottom-right corners are rounded blend: Specifies whether the color and background color should be blended together to produce the border color. *Availability*: Available in MochiKit 1.3.1+ :mochidef:`toggle(element[, effect[, options]])`: Toggle an ``element`` between visible and invisible state using an effect. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). effect: One of the visual pairs to use: ============ ========================================= ``"appear"`` :mochiref:`appear` and :mochiref:`fade` ``"blind"`` :mochiref:`blindUp` and :mochiref:`blindDown` ``"size"`` :mochiref:`grow` and :mochiref:`shrink` ``"slide"`` :mochiref:`slideUp` and :mochiref:`slideDown` ============ ========================================= options: The optional effect options (see the respective effect functions for details). *Availability*: Available in MochiKit 1.4+ :mochidef:`tagifyText(element[, tagifyStyle])`: Transform the node text into ``SPAN`` nodes each containing a single letter. Only text nodes that are immediate children will be modified by this function. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). tagifyStyle: Style to apply to each new ``SPAN`` node, defaults to ``'position: relative'``. *Availability*: Available in MochiKit 1.4+ :mochidef:`multiple(elements, effect[, options])`: Launch the same effect on a list of ``elements``. elements: A list of element ID strings or a DOM nodes (see :mochiref:`MochiKit.DOM.getElement`). effect: An effect class constructor function. options: The effect options (see the respective effect class). A special ``speed`` value will be added to the effect ``delay`` for each additional element in the list. This cause the effects to not run exactly in parallel by default. ========= ================= speed ``0.1`` delay ``0.0`` (initial) ========= ================= *Availability*: Available in MochiKit 1.4+ Combination Effects ------------------- :mochidef:`fade(element[, options])`: Fades an ``element`` using the :mochiref:`Opacity` effect. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original element opacity will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: ====== ============================================= from ``element.opacity || 1.0`` to ``0.0`` ====== ============================================= *Availability*: Available in MochiKit 1.4+ :mochidef:`appear(element [, options])`: Slowly shows an ``element`` using the :mochiref:`Opacity` effect. If the ``element`` has ``"display: none"`` style, it will be changed to ``"display: block"`` with :mochiref:`MochiKit.Style.showElement`. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: ===== ============================================= from ``element.opacity || 0.0`` to ``1.0`` ===== ============================================= *Availability*: Available in MochiKit 1.4+ :mochidef:`puff(element [, options])`: Make an ``element`` double size while also fading it using the :mochiref:`Scale` and :mochiref:`Opacity` effects in parallel. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original element size, position and opacity will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ :mochidef:`blindUp(element [, options])`: Blind an ``element`` up, changing its vertical size to 0 using the :mochiref:`Scale` effect. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original element size will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ :mochidef:`blindDown(element [, options])`: Blind an ``element`` down, restoring its vertical size using the :mochiref:`Scale` effect. If the ``element`` has ``"display: none"`` style, it will be changed to ``"display: block"`` with :mochiref:`MochiKit.Style.showElement`. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ :mochidef:`switchOff(element [, options])`: A switch-off like effect, making the ``element`` disappear, using the :mochiref:`Opacity` and :mochiref:`Scale` effects in sequence. The initial :mochiref:`Opacity` effect uses a flicker (partially random) transformation. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original element opacity, size and position will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. Note that the options will only affect the secondary :mochiref:`Scale` effect. *Availability*: Available in MochiKit 1.4+ :mochidef:`dropOut(element [, options])`: Make the element fall and fade using the :mochiref:`Move` and :mochiref:`Opacity` effects in parallel. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original element position and opacity will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: The ``distance`` option controls the number of pixels that the element will move downwards. See also the :mochiref:`DefaultOptions`. ======== ======= distance ``100`` ======== ======= *Availability*: Available in MochiKit 1.4+ :mochidef:`shake(element [, options])`: Shake an element from left to right using a sequence of six :mochiref:`Move` effects. Once the effect has completed, the original ``element`` position will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. Note that the options will only affect the last :mochiref:`Move` effect. *Availability*: Available in MochiKit 1.4+ :mochidef:`slideDown(element [, options])`: Slide an ``element`` down using the :mochiref:`Scale` effect. The ``element`` must have a fixed height and contain a single child. If the ``element`` has ``"display: none"`` style it will be changed to ``"display: block"`` with :mochiref:`MochiKit.Style.showElement`. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ :mochidef:`slideUp(element [, options])`: Slide an ``element`` up using the :mochiref:`Scale` effect. The ``element`` must have a fixed height and contain a single child. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original element size will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ :mochidef:`squish(element [, options])`: Reduce the horizontal and vertical sizes at the same time using a single :mochiref:`Scale` effect. The result is similar to the :mochiref:`shrink` effect with a ``top-left`` value for the ``direction`` option. The ``element`` should have fixed width and height. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original element size will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ :mochidef:`grow(element [, options])`: Grows an ``element`` size using :mochiref:`Scale`, :mochiref:`Move` and :mochiref:`Opacity` effects in parallel. The ``element`` should have fixed width, height and top-left position. Before the effect starts, the ``element`` will be shown with :mochiref:`MochiKit.Style.showElement` and the size and position values will be read. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: The following options and default values control this effect. Note that the :mochiref:`Opacity` effect is turned off by default. See also the :mochiref:`DefaultOptions`. ================= ======================================== direction ``"center"`` moveTransition ``MochiKit.Visual.Transitions.sinoidal`` scaleTransition ``MochiKit.Visual.Transitions.sinoidal`` opacityTransition ``MochiKit.Visual.Transitions.full`` ================= ======================================== The ``direction`` option controls the origin point of the effect. The following values are allowed: ===================== ======================================== ``"center"`` Grows from the center ``"top-left"`` Grows from the top left corner ``"top-right"`` Grows from the top right corner ``"bottom-left"`` Grows from the bottom left corner ``"bottom-right"`` Grows from the bottom right corner ===================== ======================================== *Availability*: Available in MochiKit 1.4+ :mochidef:`shrink(element [, options])`: Shrinks an ``element`` using :mochiref:`Scale`, :mochiref:`Move` and :mochiref:`Opacity` effects in parallel. The ``element`` should have fixed width, height and top-left position. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original size and position will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: The following options and default values control this effect. Note that the :mochiref:`Opacity` effect is turned off by default. See also the :mochiref:`DefaultOptions`. ================= ======================================== direction ``"center"`` moveTransition ``MochiKit.Visual.Transitions.sinoidal`` scaleTransition ``MochiKit.Visual.Transitions.sinoidal`` opacityTransition ``MochiKit.Visual.Transitions.full`` ================= ======================================== The ``direction`` option controls the destination point of the effect. The following values are allowed: ===================== ======================================== ``"center"`` Grows from the center ``"top-left"`` Grows from the top left corner ``"top-right"`` Grows from the top right corner ``"bottom-left"`` Grows from the bottom left corner ``"bottom-right"`` Grows from the bottom right corner ===================== ======================================== *Availability*: Available in MochiKit 1.4+ :mochidef:`pulsate(element [, options])`: Switches the ``element`` visibility using a pulsating :mochiref:`Opacity` effect. The effect both starts and ends with a ``0`` opacity value. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: The ``pulses`` option controls the number of pulses made during the effect. See also the :mochiref:`DefaultOptions`. ====== ======== pulses ``5`` ====== ======== *Availability*: Available in MochiKit 1.4+ :mochidef:`fold(element [, options])`: Reduce first the ``element`` vertical size, and then the horizontal size using two :mochiref:`Scale` effects in sequence. The ``element`` should have both fixed width and height. Once the effect has completed, the ``element`` will be hidden with :mochiref:`MochiKit.Style.hideElement` and the original size and position will be restored. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. Note that the options will only affect the first :mochiref:`Scale` effect. *Availability*: Available in MochiKit 1.4+ Basic Effects Classes & Constants --------------------------------- :mochidef:`Transitions`: Default transition functions available for all effects. A transition function adjusts the current position value between 0 and 1 in order to achieve a non-linear sequence of position values for the effect. =========== ======================================== linear A straight linear transition. sinoidal A smooth sine value transition. reverse A reverse linear transition. flicker A sine transition with random additions. wobble A multi-period sine curve transition with 4.5 wobbles and ending with one (1). pulse A multi-period triangle curve transition with 5 pulses (by default) and ending with zero (0). parabolic A smooth parabolic transition. none A fixed zero (0) value transition. full A fixed one (1) value transition. =========== ======================================== *Availability*: Available in MochiKit 1.4+ :mochidef:`DefaultOptions`: Default options for all effects. Note that all effects inherit the :mochiref:`Base` class and thereby also support a number of events that can be specified as callback functions among the effect options. =========== ======================================== transition ``MochiKit.Visual.Transitions.sinoidal`` duration ``1.0`` (seconds) fps ``25.0`` sync ``false`` (only set for :mochiref:`Parallel` or :mochiref:`Sequence` effects) from ``0.0`` to ``1.0`` delay ``0.0`` queue ``'parallel'`` =========== ======================================== *Availability*: Available in MochiKit 1.4+ :mochidef:`Base()`: Base class to all effects. Define a basic looping service, use it for creating new effects. You can override the methods ``setup``, ``update`` and ``finish``. The class defines a number of events that will be called during effect life. The events are: - beforeStart - beforeSetup - beforeUpdate - afterUpdate - beforeFinish - afterFinish If you want to define your own callbacks, define it in the options parameter of the effect. Example:: // I slide it up and then down again slideUp('myelement', {afterFinish: function () { slideDown('myelement'); }); Specific ``internal`` events are also available: for each one listed above, the same exists with an 'Internal' postfix (e.g. 'beforeStartInternal'). Their purpose is mainly for creating your own effect and keep the user access to event callbacks (not overriding the library ones). *Availability*: Available in MochiKit 1.4+ :mochidef:`Parallel(effects [, options])`: Launch a list of ``effects`` in parallel. effects: An array of instantiated effect objects. Note that they *must* all have ``sync`` set to ``true``. options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ :mochidef:`Sequence(effects [, options])`: Launch a list of ``effects`` in sequence, one after the other. effects: An array of instantiated effect objects. Note that they *must* all have ``sync`` set to ``true``. options: See :mochiref:`DefaultOptions`. Note that the default value for some options is different and that some of the transition and timing options don't make sense to override. =========== ======================================== transition ``MochiKit.Visual.Transitions.linear`` duration Sum of the ``duration`` for all ``effects``. from Only ``0.0`` makes sense. to Only ``1.0`` makes sense. =========== ======================================== *Availability*: Available in MochiKit 1.4+ :mochidef:`Opacity(element [, options])`: Change the opacity of an ``element`` progressively. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: The following options and default values control this effect. See also the :mochiref:`DefaultOptions`. ====== ======== from ``0.0`` to ``1.0`` ====== ======== *Availability*: Available in MochiKit 1.4+ :mochidef:`Move(element [, options])`: Changes the (top left) position of an ``element`` in small steps, creating a moving effect. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: The following options and default values control this effect. See also the :mochiref:`DefaultOptions`. ========= ================ x ``0`` y ``0`` mode ``'relative'`` ========= ================ The ``mode`` option controls if the specified ``x`` and ``y`` coordinates are ``relative`` or ``absolute`` with respect to the current ``element`` position. *Availability*: Available in MochiKit 1.4+ :mochidef:`Scale(element, percent [, options])`: Changes the size of an ``element``. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). percent: Final wanted size in percent of current size. The size will be reduced if the value is between 0 and 100, and raised if the value is above 100. options: The following options and default values control this effect. See also the :mochiref:`DefaultOptions`. ================ ============ scaleX ``true`` scaleY ``true`` scaleContent ``true`` scaleFromCenter ``false`` scaleMode ``"box"`` scaleFrom ``100.0`` scaleTo ``percent`` ================ ============ The ``scaleContent`` option controls if the element ``font-size`` should also be scaled along with the size. The ``scaleFromCenter`` option allows continual adjustment of the ``element`` top left position to keep the element centered during the size change. The ``scaleMode`` option is used to determine the original ``element`` size. It can have one of the following values: ================ ========================================= ``"box"`` Uses ``offsetHeight`` and ``offsetWidth`` ``"contents"`` Uses ``scrollHeight`` and ``scrollWidth`` {...} Uses ``originalHeight`` and ``originalWidth`` from the specified object ================ ========================================= *Availability*: Available in MochiKit 1.4+ :mochidef:`Highlight(element [, options])`: Highlights an ``element`` by flashing the background color. The color is first set to the ``startcolor`` and is then slowly morphed into the ``endcolor``, normally the original background color of the element. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: The following options and default values control this effect. See also the :mochiref:`DefaultOptions`. =========== ============== startcolor ``'#ffff99'`` endcolor ``element.style.backgroundColor`` =========== ============== *Availability*: Available in MochiKit 1.4+ :mochidef:`ScrollTo(element [, options])`: Scroll the window to the position of the given ``element``. Note that this effect only scrolls the top window and not any parent elements with scrollbars due to ``"overflow: auto"`` style. element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ :mochidef:`Morph(element [, options])`: Make a transformation to the given ``element``. It's called with the option ``style`` with an array holding the styles to change. It works with properties for size (``font-size``, ``border-width``, ...) and properties for color (``color``, ``background-color``, ...). For size, it's better to have defined the original style. You *must* use the same unit in the call to Morph (no translation exists between two different units). Parsed length are postfixed with: em, ex, px, in, cm, mm, pt, pc. Example::
MyDiv
... Morph("foo", {"style": {"font-size": "2em"}}); element: An element ID string or a DOM node (see :mochiref:`MochiKit.DOM.getElement`). options: See :mochiref:`DefaultOptions`. *Availability*: Available in MochiKit 1.4+ Authors ======= - Kevin Dangoor - Bob Ippolito - Thomas Herve - Round corners originally adapted from Rico (though little remains) - Effects originally adapted from Script.aculo.us Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php Portions adapted from `Rico`_ are available under the terms of the `Apache License, Version 2.0`_. Portions adapted from `Scriptaculous`_ are available under the terms of the `MIT License`_. .. _`Apache License, Version 2.0`: http://www.apache.org/licenses/LICENSE-2.0.html MochiKit-1.4.2/doc/rst/MochiKit/index.rst0000660000175000017500000000560711102215564017227 0ustar scottscott.. title:: MochiKit Documentation Index Distribution ============ MochiKit - makes JavaScript suck a bit less - :mochiref:`MochiKit.Async` - manage asynchronous tasks - :mochiref:`MochiKit.Base` - functional programming and useful comparisons - :mochiref:`MochiKit.DOM` - painless DOM manipulation API - :mochiref:`MochiKit.DragAndDrop` - drag and drop - :mochiref:`MochiKit.Color` - color abstraction with CSS3 support - :mochiref:`MochiKit.DateTime` - "what time is it anyway?" - :mochiref:`MochiKit.Format` - string formatting goes here - :mochiref:`MochiKit.Iter` - itertools for JavaScript; iteration made HARD, and then easy - :mochiref:`MochiKit.Logging` - we're all tired of ``alert()`` - :mochiref:`MochiKit.LoggingPane` - interactive :mochiref:`MochiKit.Logging` pane - :mochiref:`MochiKit.Selector` - selecting elements by CSS selector syntax - :mochiref:`MochiKit.Signal` - simple universal event handling - :mochiref:`MochiKit.Style` - painless CSS manipulation API - :mochiref:`MochiKit.Sortable` - sortable - :mochiref:`MochiKit.Visual` - visual effects Notes ===== To turn off MochiKit's export feature (which may be necessary for compatibility with some existing code), do this before loading MochiKit:: When export mode is off, you must use fully qualified names for all MochiKit functions (e.g. ``MochiKit.Base.map(...)``). Screencasts =========== - `MochiKit 1.1 Intro`__ .. __: http://mochikit.com/screencasts/MochiKit_Intro-1 See Also ======== .. _`mochikit.com`: http://mochikit.com/ .. _`from __future__ import *`: http://bob.pythonmac.org/ .. _`MochiKit and Dojo`: http://trac.mochikit.com/wiki/HowToUseWithDojo .. _`MochiKit on JSAN`: http://openjsan.org/doc/b/bo/bob/MochiKit/ .. _`MochiKit tag on del.icio.us`: http://del.icio.us/tag/mochikit .. _`MochiKit tag on Technorati`: http://technorati.com/tag/mochikit .. _`Google Groups: MochiKit`: http://groups.google.com/group/mochikit - `Google Groups: MochiKit`_: The official mailing list for discussions related to development of and with MochiKit - `mochikit.com`_: MochiKit's home on the web - `from __future__ import *`_: Bob Ippolito's blog - `MochiKit and Dojo`_: information for using MochiKit with Dojo Toolkit - `MochiKit on JSAN`_: the JSAN distribution page for MochiKit - `MochiKit tag on del.icio.us`_: Recent bookmarks related to MochiKit - `MochiKit tag on Technorati`_: Recent blog entries related to MochiKit Version History =============== .. include:: VersionHistory.rst Copyright ========= Copyright 2005 Bob Ippolito . This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the `MIT License`_ or the `Academic Free License v2.1`_. .. _`MIT License`: http://www.opensource.org/licenses/mit-license.php .. _`Academic Free License v2.1`: http://www.opensource.org/licenses/afl-2.1.php MochiKit-1.4.2/doc/html/0000755000175000017500000000000011136470264014014 5ustar scottscottMochiKit-1.4.2/doc/html/MochiKit/0000755000175000017500000000000011136470264015523 5ustar scottscottMochiKit-1.4.2/doc/html/MochiKit/VersionHistory.html0000660000175000017500000005243111113647640021422 0ustar scottscott
MochiKit Back to docs index

2008-11-27 v1.4.2 (bug fix release)

  • Changed default packed version to contain all modules (since easy customization is now available).
  • More fixes in MochiKit.Style.getElementDimensions for IE and hidden elements (#325).
  • Fixed issue in MochiKit.Style.getViewportDimensions when called within the document HEAD.
  • Fixed MochiKit.DOM.coerceToDOM() handling of arrays when MochiKit.Iter is not loaded (#328).

2008-11-02 v1.4.1 (bug fix release)

  • Added export of deprecated MochiKit.DOM.computedStyle function (#324).
  • Fixed issue in MochiKit.Style.getElementDimensions when elements are hidden due to CSS class definitions (#325).
  • Moved makePositioned, undoPositioned, makeClipping and undoClipping from MochiKit.DOM to MochiKit.Style due to circular dependency (#327).
  • Fixed makeClipping and undoClipping to handle overflow-x and overflow-y styles correctly (#326).
  • Fixed issue with Event.relatedTarget() sometimes returning XUL elements in Mozilla-based browsers (#322).

2008-10-21 v1.4

  • Added pt_BR to MochiKit.Format.LOCALE.
  • MochiKit.Async now sets the "X-Requested-With: XMLHttpRequest" header, a de facto standard (Prototype, jQuery, Mootools).
  • MochiKit.Signal custom handlers no longer cause callbacks to get re-bound to the source if they were previously bound.
  • Fixed MochiKit.Signal.signal re-entrancy bug that could cause recently disconnected slots to get signaled.
  • MochiKit.Base.evalJSON will now evaluate JSON that is wrapped in a /* comment block */.
  • MochiKit.Color's HSV to RGB conversion code fixed to return the correct value (hsv.v for RGB values) in cases where saturation === 0.
  • doXHR workaround for a Mozilla bug when calling XMLHttpRequest in certain situations. Always wraps call in a callLater(0, doXHR, url, opts).
  • parseQueryString will now parse values with embedded "="
  • Workaround for a Safari DOM crash when using MochiKit.Iter.list. http://bugs.webkit.org/show_bug.cgi?id=12191
  • New removeNodeAttribute function in MochiKit.DOM.
  • MochiKit.Async.doXHR and dependent functions now accept 201 CREATED and 204 NO CONTENT as valid.
  • MochiKit.DOM.formContents now treats option tags the same way that form posts do in the case of missing and empty string value attributes, even in IE.
  • MochiKit.Base.queryString now accepts third queryString([names, values]) form.
  • MochiKit.DOM.formContents now defaults to document.body if no element is given.
  • New MochiKit.Selector module (still somewhat experimental)
  • MochiKit.LoggingPane fixes for Internet Explorer
  • MochiKit.DOM now creates XHTML nodes in XUL documents.
  • MochiKit.LoggingPane now works on pages with '#' in the URL on IE
  • New MochiKit.Async.doXHR as a convenient method for doing custom XMLHttpRequests (e.g. extra headers, overrideMimeType, etc.)
  • New __connect__ protocol for MochiKit.Signal.connect source notifications
  • Added colSpan, bgColor to the list of DOM renames for Internet Explorer
  • New MochiKit.Signal.disconnectAllTo function
  • MochiKit.Base.parseQueryString now accepts leading question mark
  • New MochiKit.Base.values function
  • Fixed MochiKit.Signal.disconnect when called from a signal handler invoked by MochiKit.Signal.signal
  • parseQueryString now splits on HTML entities equivalent to ampersand as well
  • Better XHTML compatibility (removed obvious cases where uppercase tagName or nodeName was assumed)
  • MochiKit.Base.queryString now handles array values in the same way HTML forms handle multiple elements of the same name.
  • MochiKit.Base.parseQueryString now returns {} for empty query string instead of {"": "undefined"}
  • MochiKit.DOM.formContents now handles option value="" correctly.
  • MochiKit.DOM now checks for undefined className.
  • MochiKit.Iter.groupby() now uses compare() to group rather than == and !=
  • serializeJSON no longer serializes undefined, as per the JSON spec
  • Fixed an infinite recursion bug in serializeJSON if an adapter returns the object itself.
  • Fixed vertical tab and control char encoding in serializeJSON (#313).
  • New MochiKit.Base.operator.seq and sne to support strict comparison
  • MochiKit.Base.isArrayLike no longer returns true for DOM text nodes
  • Added readonly-readOnly to the list of DOM renames for Internet Explorer
  • New MochiKit.Signal event method: confirmUnload (sets returnValue for onbeforeunload)
  • Fix interpreter help() function for Firefox and IE
  • API version compatibility notes added
  • New MochiKit.Base functions methodcaller and compose
  • Support IE-based native console logging (Debugger, Atlas)
  • Refactored style functions from MochiKit.DOM to MochiKit.Style
  • MochiKit.Async.DeferredList is now a proper Deferred
  • MochiKit.DOM.formContents now supports SELECT multiple tags
  • Re-use StopIteration Error if the browser already has it
  • Workaround IE type="" bug for INPUT elements
  • Allow LoggingPane to work in IE with hyphen-containing URLs
  • Replace percents for Safari native logging to avoid crashing
  • New MochiKit.DOM.coerceToDOM .dom(node) / .__dom__(node) protocol
  • MochiKit.DOM's MochiKit.Iter dependency is now optional
  • Added expand all link to the documentation index
  • Added MochiKit.DOM.isChildNode function.
  • Added synthesizing for onmouseenter/onmouseleave
  • Added animation functions and classes to MochiKit.Visual.
  • Added MochiKit.Style.getElementDimensions support for calculating the actual content size (without padding and borders).
  • Added MochiKit.DOM.insertSiblingNodesBefore, getFirstElementByTagAndClassName, getFirstParentByTagAndClassName, makeClipping, makePositioned, undoClipping, undoPositioned and removeEmptyTextNodes functions.
  • Added MochiKit.Base.bindLate, camelize, flattenArray, mean, median and noop functions.
  • New MochiKit.DragAndDrop module for drag and drop handling.
  • New MochiKit.Sortable module for lists sortable with drag and drop.
  • Changed MochiKit.Signal.connect to use late function binding also for non-DOM signals (#307).
  • Fixed MochiKit.Color.isColor when symbols not exported (#296).
  • Added support for inclusion in SVG files (#290).
  • Fixed rounding errors in MochiKit.Format.twoDigitFloat (#275).
  • Fixed MochiKit.Logging to convert log levels to strings (#273).
  • Fixed MochiKit.Iter.forEach and iextend for array-like objects with and iter function (#268).

2006-04-29 v1.3.1 (bug fix release)

  • Fix sendXMLHttpRequest sendContent regression
  • Internet Explorer fix in MochiKit.Logging (printfire exception)
  • Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async

2006-04-26 v1.3 "warp zone"

  • IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)
  • IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)
  • New MochiKit.Base.method as a convenience form of bind that takes the object before the method
  • New MochiKit.Base.flattenArguments for flattening a list of arguments to a single Array
  • Refactored MochiRegExp example to use MochiKit.Signal
  • New key_events example demonstrating use of MochiKit.Signal's key handling capabilities.
  • MochiKit.DOM.createDOM API change for convenience: if attrs is a string, null is used and the string will be considered the first node. This allows for the more natural P("foo") rather than P(null, "foo").
  • MochiKit Interpreter example refactored to use MochiKit.Signal and now provides multi-line input and a help() function to get MochiKit function signature from the documentation.
  • Native Console Logging for the default MochiKit.Logging logger
  • New MochiKit.Async.DeferredList, gatherResults, maybeDeferred
  • New MochiKit.Signal example: draggable
  • Added sanity checking to Deferred to ensure that errors happen when chaining is used incorrectly
  • Opera sendXMLHttpRequest fix (sends empty string instead of null by default)
  • Fix a bug in MochiKit.Color that incorrectly generated hex colors for component values smaller than 16/255.
  • Fix a bug in MochiKit.Logging that prevented logs from being capped at a maximum size
  • MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof Error, so that the errback chain is used instead of the callback chain.
  • MochiKit.DOM.appendChildNodes and associated functions now append iterables in the correct order.
  • New MochiKit-based SimpleTest test runner as a replacement for Test.Simple
  • MochiKit.Base.isNull no longer matches undefined
  • example doctypes changed to HTML4
  • isDateLike no longer throws error on null
  • New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt
  • updated elementDimensions to calculate width from offsetWidth instead of clientWidth
  • formContents now works with FORM tags that have a name attribute
  • Documentation now uses MochiKit to generate a function index

2006-01-26 v1.2 "the ocho"

  • Fixed MochiKit.Color.Color.lighterColorWithLevel
  • Added new MochiKit.Base.findIdentical function to find the index of an element in an Array-like object. Uses === for identity comparison.
  • Added new MochiKit.Base.find function to find the index of an element in an Array-like object. Uses compare for rich comparison.
  • MochiKit.Base.bind will accept a string for func, which will be immediately looked up as self[func].
  • MochiKit.DOM.formContents no longer skips empty form elements for Zope compatibility
  • MochiKit.Iter.forEach will now catch StopIteration to break
  • New MochiKit.DOM.elementDimensions(element) for determining the width and height of an element in the document
  • MochiKit.DOM's initialization is now compatible with HTMLUnit + JWebUnit + Rhino
  • MochiKit.LoggingPane will now re-use a _MochiKit_LoggingPane DIV element currently in the document instead of always creating one.
  • MochiKit.Base now has operator.mul
  • MochiKit.DOM.formContents correctly handles unchecked checkboxes that have a custom value attribute
  • Added new MochiKit.Color constructors fromComputedStyle and fromText
  • MochiKit.DOM.setNodeAttribute should work now
  • MochiKit.DOM now has a workaround for an IE bug when setting the style property to a string
  • MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the name and for properties
  • MochiKit.DOM.scrapeText now walks the DOM tree in-order
  • MochiKit.LoggingPane now sanitizes the window name to work around IE bug
  • MochiKit.DOM now translates usemap to useMap to work around IE bug
  • MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks
  • Added new MochiKit.DOM documentation on element visibility
  • New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}]) for determining the position of an element in the document
  • Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG

2005-11-14 v1.1

  • Fixed a bug in numberFormatter with large numbers
  • Massively overhauled documentation
  • Fast-path for primitives in MochiKit.Base.compare
  • New groupby and groupby_as_array in MochiKit.Iter
  • Added iterator factory adapter for objects that implement iterateNext()
  • Fixed isoTimestamp to handle timestamps with time zone correctly
  • Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP, LEGEND, FIELDSET
  • New MochiKit.DOM formContents and enhancement to queryString to support it
  • Updated view_source example to use dp.SyntaxHighlighter 1.3.0
  • MochiKit.LoggingPane now uses named windows based on the URL so that a given URL will get the same LoggingPane window after a reload (at the same position, etc.)
  • MochiKit.DOM now has currentWindow() and currentDocument() context variables that are set with withWindow() and withDocument(). These context variables affect all MochiKit.DOM functionality (getElement, createDOM, etc.)
  • MochiKit.Base.items will now catch and ignore exceptions for properties that are enumerable but not accessible (e.g. permission denied)
  • MochiKit.Async.Deferred's addCallback/addErrback/addBoth now accept additional arguments that are used to create a partially applied function. This differs from Twisted in that the callback/errback result becomes the last argument, not the first when this feature is used.
  • MochiKit.Async's doSimpleXMLHttpRequest will now accept additional arguments which are used to create a GET query string
  • Did some refactoring to reduce the footprint of MochiKit by a few kilobytes
  • escapeHTML to longer escapes ' (apos) and now uses String.replace instead of iterating over every char.
  • Added DeferredLock to Async
  • Renamed getElementsComputedStyle to computedStyle and moved it from MochiKit.Visual to MochiKit.DOM
  • Moved all color support out of MochiKit.Visual and into MochiKit.Color
  • Fixed range() to accept a negative step
  • New alias to MochiKit.swapDOM called removeElement
  • New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets an attribute on a node without raising, roughly equivalent to: updateNodeAttributes(node, {attr: value})
  • New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of a node's attribute or returns null without raising
  • Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack directly (addLoadEvent did not leak, since it clears the handler)

2005-10-24 v1.0

  • New interpreter example that shows usage of MochiKit.DOM to make an interactive JavaScript interpreter
  • New MochiKit.LoggingPane for use with the MochiKit.Logging debuggingBookmarklet, with logging_pane example to show its usage
  • New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async in order to provide a live regular expression matching tool
  • Added advanced number formatting capabilities to MochiKit.Format: numberFormatter(pattern, placeholder="", locale="default") and formatLocale(locale="default")
  • Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.
  • Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE
  • Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision) to MochiKit.Format
  • MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically isoTimestamp(isoString) will convert them to Date objects, and toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC
  • Fixed missing errback for sendXMLHttpRequest when the server does not respond
  • Fixed infinite recusion bug when using roundClass("DIV", ...)
  • Fixed a bug in MochiKit.Async wait (and callLater) that prevented them from being cancelled properly
  • Workaround in MochiKit.Base bind (and partial) for functions that don't have an apply method, such as alert
  • Reliably return null from the string parsing/manipulation functions if the input can't be coerced to a string (s + "") or the input makes no sense; e.g. isoTimestamp(null) and isoTimestamp("") return null

2005-10-08 v0.90

  • Fixed ISO compliance with toISODate
  • Added missing operator.sub
  • Placated Mozilla's strict warnings a bit
  • Added JSON serialization and unserialization support to MochiKit.Base: serializeJSON, evalJSON, registerJSON. This is very similar to the repr API.
  • Fixed a bug in the script loader that failed in some scenarios when a script tag did not have a "src" attribute (thanks Ian!)
  • Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA, P, FORM
  • Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode and parseQueryString, when available.

2005-08-12 v0.80

  • Source highlighting in all examples, moved to a view-source example
  • Added some experimental syntax highlighting for the Rounded Corners example, via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib
  • Use an indirect binding for the logger conveniences, so that the global logger could be replaced by setting MochiKit.Logger.logger to something else (though an observer is probably a better choice).
  • Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent, which will be looked up with getElement
  • Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of node.parentNode)
  • Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success
  • Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues
  • Possible workaround for Safari issue with swapDOM, where it would get confused because two elements were in the DOM at the same time with the same id
  • Added missing THEAD convenience function to MochiKit.DOM
  • Added lstrip, rstrip, strip to MochiKit.Format
  • Added updateNodeAttributes, appendChildNodes, replaceChildNodes to MochiKit.DOM
  • MochiKit.Iter.iextend now has a fast-path for array-like objects
  • Added HSV color space support to MochiKit.Visual
  • Fixed a bug in the sortable_tables example, it now converts types correctly
  • Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global scope

2005-08-04 v0.70

  • New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and a little TAL-ish DOM templating attribute language.
  • sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer ignore requests with status == 0, which seems to happen for cached or local requests
  • Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.
  • Changed scrapeText API to return a string by default. This is API-breaking! It was dumb to have the default return value be the form you almost never want. Sorry.
  • Added special form to swapDOM(dest, src). If src is null, dest is removed (where previously you'd likely get a DOM exception).
  • Added three new functions to MochiKit.Base for dealing with URL query strings: urlEncode, queryString, parseQueryString
  • MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name starts with "on" (e.g. "onclick"). If v is a string, it will set it to new Function(v).
  • Another workaround for Internet "worst browser ever" Explorer's setAttribute usage in MochiKit.DOM.createDOM (checked -> defaultChecked).
  • Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM
  • Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller now!

2005-07-29 v0.60

  • Beefed up the MochiKit.DOM test suite
  • Fixed return value for MochiKit.DOM.swapElementClass, could return false unexpectedly before
  • Added an optional "parent" argument to MochiKit.DOM.getElementsByTagAndClassName
  • Added a "packed" version in packed/lib/MochiKit/MochiKit.js
  • Changed build script to rewrite the URLs in tests to account for the JSAN-required reorganization
  • MochiKit.Compat to potentially work around IE 5.5 issues (5.0 still not supported). Test.Simple doesn't seem to work there, though.
  • Several minor documentation corrections

2005-07-27 v0.50

  • Initial Release
MochiKit-1.4.2/doc/html/MochiKit/Visual.html0000660000175000017500000014767611113647640017676 0ustar scottscott MochiKit.Visual - visual effects MochiKit Back to docs index

Name

MochiKit.Visual - visual effects

Synopsis

// round the corners of all h1 elements
roundClass("h1", null);

// round the top left corner of the element with the id "title"
roundElement("title", {corners: "tl"});

// Add an fade effect to an element
fade('myelement');

Description

MochiKit.Visual provides visual effects and animations for HTML elements.

Overview

MochiKit.Visual provides different visual effects: rounded corners and animations for your HTML elements. Rounded corners are created completely through CSS manipulations and require no external images or style sheets. This implementation was adapted from Rico. Dynamic effects are ported from Scriptaculous.

Animations & Effects

Dynamic or animated effects are managed by a basic looping service (see Base). The effect looping is controlled by timers that are invoked at regular and short intervals while the effect is executing. The base looping service takes the current system time into consideration, automatically skipping effect steps on execution delays.

The effect classes need only handle dynamic updates based on a floating-point number between 0.0 and 1.0 (the effect position). This effect position may also be manipulated by Transitions to provide non-linear updates, which may further enhance the visual effect.

The effect timer and transitions can be controlled through a set of DefaultOptions that are available for all effect classes.

The Effects Queue

When you create effects based on user input (mouse clicks for example), it can create conflicts between the effects if multiple effects are running at the same time. To manage this problem, the Queue mechanism has been introduced: it's responsible for running the effects as you desired.

By default, you have one Queue called 'global', and the effects run in 'parallel' (see DefaultOptions). Every effect has a queue option to customize this. Its value can be a string, thereby using the global scope:

  • front: the effect will be run before any other non-started effect;
  • end: the effect will be run when all other effects have finished;
  • break: every other effect is immediately finalized when the the effect start;
  • parallel: the effect runs in parallel with other effects.

But you have even more control if you use an object with the following property keys:

  • position takes one of the values listed above;
  • scope contains the queue name. If it's "global" the effect will use the default queue, otherwise you can define your own queue name. For example, if you add an effect on a specified element, you may use the element id as scope;
  • limit defines how many effects can be stored in the queue at a single time. If an effect is added when the limit has been reached, it will never be run (it's lost).

API Reference

Functions

roundClass(tagName[, className[, options]]):

Rounds all of the elements that match the tagName and className specifiers, using the options provided. tagName or className can be null to match all tags or classes. Regarding the options, see the roundElement function.

Availability:
Available in MochiKit 1.3.1+

roundElement(element[, options]):

Immediately round the corners of the specified element.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:

The options mapping has the following defaults:

corners "all"
color "fromElement"
bgColor "fromParent"
blend true
border false
compact false

The options parameters can have following values:

corners:

Specifies which corners of the element should be rounded. Choices are:

  • all
  • top
  • bottom
  • tl (top left)
  • bl (bottom left)
  • tr (top right)
  • br (bottom right)
Example:
"tl br": top-left and bottom-right corners are rounded
blend:
Specifies whether the color and background color should be blended together to produce the border color.
Availability:
Available in MochiKit 1.3.1+

toggle(element[, effect[, options]]):

Toggle an element between visible and invisible state using an effect.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
effect:

One of the visual pairs to use:

"appear" appear and fade
"blind" blindUp and blindDown
"size" grow and shrink
"slide" slideUp and slideDown
options:
The optional effect options (see the respective effect functions for details).
Availability:
Available in MochiKit 1.4+

tagifyText(element[, tagifyStyle]):

Transform the node text into SPAN nodes each containing a single letter. Only text nodes that are immediate children will be modified by this function.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
tagifyStyle:
Style to apply to each new SPAN node, defaults to 'position: relative'.
Availability:
Available in MochiKit 1.4+

multiple(elements, effect[, options]):

Launch the same effect on a list of elements.

elements:
A list of element ID strings or a DOM nodes (see MochiKit.DOM.getElement).
effect:
An effect class constructor function.
options:

The effect options (see the respective effect class). A special speed value will be added to the effect delay for each additional element in the list. This cause the effects to not run exactly in parallel by default.

speed 0.1
delay 0.0 (initial)
Availability:
Available in MochiKit 1.4+

Combination Effects

fade(element[, options]):

Fades an element using the Opacity effect. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original element opacity will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
from element.opacity || 1.0
to 0.0
Availability:
Available in MochiKit 1.4+

appear(element [, options]):

Slowly shows an element using the Opacity effect. If the element has "display: none" style, it will be changed to "display: block" with MochiKit.Style.showElement.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
from element.opacity || 0.0
to 1.0
Availability:
Available in MochiKit 1.4+

puff(element [, options]):

Make an element double size while also fading it using the Scale and Opacity effects in parallel. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original element size, position and opacity will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

blindUp(element [, options]):

Blind an element up, changing its vertical size to 0 using the Scale effect. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original element size will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

blindDown(element [, options]):

Blind an element down, restoring its vertical size using the Scale effect. If the element has "display: none" style, it will be changed to "display: block" with MochiKit.Style.showElement.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

switchOff(element [, options]):

A switch-off like effect, making the element disappear, using the Opacity and Scale effects in sequence. The initial Opacity effect uses a flicker (partially random) transformation. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original element opacity, size and position will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions. Note that the options will only affect the secondary Scale effect.
Availability:
Available in MochiKit 1.4+

dropOut(element [, options]):

Make the element fall and fade using the Move and Opacity effects in parallel. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original element position and opacity will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:

The distance option controls the number of pixels that the element will move downwards. See also the DefaultOptions.

distance 100
Availability:
Available in MochiKit 1.4+

shake(element [, options]):

Shake an element from left to right using a sequence of six Move effects. Once the effect has completed, the original element position will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions. Note that the options will only affect the last Move effect.
Availability:
Available in MochiKit 1.4+

slideDown(element [, options]):

Slide an element down using the Scale effect. The element must have a fixed height and contain a single child. If the element has "display: none" style it will be changed to "display: block" with MochiKit.Style.showElement.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

slideUp(element [, options]):

Slide an element up using the Scale effect. The element must have a fixed height and contain a single child. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original element size will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

squish(element [, options]):

Reduce the horizontal and vertical sizes at the same time using a single Scale effect. The result is similar to the shrink effect with a top-left value for the direction option. The element should have fixed width and height. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original element size will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

grow(element [, options]):

Grows an element size using Scale, Move and Opacity effects in parallel. The element should have fixed width, height and top-left position. Before the effect starts, the element will be shown with MochiKit.Style.showElement and the size and position values will be read.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:

The following options and default values control this effect. Note that the Opacity effect is turned off by default. See also the DefaultOptions.

direction "center"
moveTransition MochiKit.Visual.Transitions.sinoidal
scaleTransition MochiKit.Visual.Transitions.sinoidal
opacityTransition MochiKit.Visual.Transitions.full

The direction option controls the origin point of the effect. The following values are allowed:

"center" Grows from the center
"top-left" Grows from the top left corner
"top-right" Grows from the top right corner
"bottom-left" Grows from the bottom left corner
"bottom-right" Grows from the bottom right corner
Availability:
Available in MochiKit 1.4+

shrink(element [, options]):

Shrinks an element using Scale, Move and Opacity effects in parallel. The element should have fixed width, height and top-left position. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original size and position will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:

The following options and default values control this effect. Note that the Opacity effect is turned off by default. See also the DefaultOptions.

direction "center"
moveTransition MochiKit.Visual.Transitions.sinoidal
scaleTransition MochiKit.Visual.Transitions.sinoidal
opacityTransition MochiKit.Visual.Transitions.full

The direction option controls the destination point of the effect. The following values are allowed:

"center" Grows from the center
"top-left" Grows from the top left corner
"top-right" Grows from the top right corner
"bottom-left" Grows from the bottom left corner
"bottom-right" Grows from the bottom right corner
Availability:
Available in MochiKit 1.4+

pulsate(element [, options]):

Switches the element visibility using a pulsating Opacity effect. The effect both starts and ends with a 0 opacity value.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:

The pulses option controls the number of pulses made during the effect. See also the DefaultOptions.

pulses 5
Availability:
Available in MochiKit 1.4+

fold(element [, options]):

Reduce first the element vertical size, and then the horizontal size using two Scale effects in sequence. The element should have both fixed width and height. Once the effect has completed, the element will be hidden with MochiKit.Style.hideElement and the original size and position will be restored.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions. Note that the options will only affect the first Scale effect.
Availability:
Available in MochiKit 1.4+

Basic Effects Classes & Constants

Transitions:

Default transition functions available for all effects. A transition function adjusts the current position value between 0 and 1 in order to achieve a non-linear sequence of position values for the effect.

linear A straight linear transition.
sinoidal A smooth sine value transition.
reverse A reverse linear transition.
flicker A sine transition with random additions.
wobble A multi-period sine curve transition with 4.5 wobbles and ending with one (1).
pulse A multi-period triangle curve transition with 5 pulses (by default) and ending with zero (0).
parabolic A smooth parabolic transition.
none A fixed zero (0) value transition.
full A fixed one (1) value transition.
Availability:
Available in MochiKit 1.4+

DefaultOptions:

Default options for all effects. Note that all effects inherit the Base class and thereby also support a number of events that can be specified as callback functions among the effect options.

transition MochiKit.Visual.Transitions.sinoidal
duration 1.0 (seconds)
fps 25.0
sync false (only set for Parallel or Sequence effects)
from 0.0
to 1.0
delay 0.0
queue 'parallel'
Availability:
Available in MochiKit 1.4+

Base():

Base class to all effects. Define a basic looping service, use it for creating new effects.

You can override the methods setup, update and finish.

The class defines a number of events that will be called during effect life. The events are:

  • beforeStart
  • beforeSetup
  • beforeUpdate
  • afterUpdate
  • beforeFinish
  • afterFinish

If you want to define your own callbacks, define it in the options parameter of the effect. Example:

// I slide it up and then down again
slideUp('myelement', {afterFinish: function () {
    slideDown('myelement');
});

Specific internal events are also available: for each one listed above, the same exists with an 'Internal' postfix (e.g. 'beforeStartInternal'). Their purpose is mainly for creating your own effect and keep the user access to event callbacks (not overriding the library ones).

Availability:
Available in MochiKit 1.4+

Parallel(effects [, options]):

Launch a list of effects in parallel.

effects:
An array of instantiated effect objects. Note that they must all have sync set to true.
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

Sequence(effects [, options]):

Launch a list of effects in sequence, one after the other.

effects:
An array of instantiated effect objects. Note that they must all have sync set to true.
options:

See DefaultOptions. Note that the default value for some options is different and that some of the transition and timing options don't make sense to override.

transition MochiKit.Visual.Transitions.linear
duration Sum of the duration for all effects.
from Only 0.0 makes sense.
to Only 1.0 makes sense.
Availability:
Available in MochiKit 1.4+

Opacity(element [, options]):

Change the opacity of an element progressively.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:

The following options and default values control this effect. See also the DefaultOptions.

from 0.0
to 1.0
Availability:
Available in MochiKit 1.4+

Move(element [, options]):

Changes the (top left) position of an element in small steps, creating a moving effect.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:

The following options and default values control this effect. See also the DefaultOptions.

x 0
y 0
mode 'relative'

The mode option controls if the specified x and y coordinates are relative or absolute with respect to the current element position.

Availability:
Available in MochiKit 1.4+

Scale(element, percent [, options]):

Changes the size of an element.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
percent:
Final wanted size in percent of current size. The size will be reduced if the value is between 0 and 100, and raised if the value is above 100.
options:

The following options and default values control this effect. See also the DefaultOptions.

scaleX true
scaleY true
scaleContent true
scaleFromCenter false
scaleMode "box"
scaleFrom 100.0
scaleTo percent

The scaleContent option controls if the element font-size should also be scaled along with the size. The scaleFromCenter option allows continual adjustment of the element top left position to keep the element centered during the size change. The scaleMode option is used to determine the original element size. It can have one of the following values:

"box" Uses offsetHeight and offsetWidth
"contents" Uses scrollHeight and scrollWidth
{...} Uses originalHeight and originalWidth from the specified object
Availability:
Available in MochiKit 1.4+

Highlight(element [, options]):

Highlights an element by flashing the background color. The color is first set to the startcolor and is then slowly morphed into the endcolor, normally the original background color of the element.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:

The following options and default values control this effect. See also the DefaultOptions.

startcolor '#ffff99'
endcolor element.style.backgroundColor
Availability:
Available in MochiKit 1.4+

ScrollTo(element [, options]):

Scroll the window to the position of the given element. Note that this effect only scrolls the top window and not any parent elements with scrollbars due to "overflow: auto" style.

element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

Morph(element [, options]):

Make a transformation to the given element. It's called with the option style with an array holding the styles to change. It works with properties for size (font-size, border-width, ...) and properties for color (color, background-color, ...).

For size, it's better to have defined the original style. You must use the same unit in the call to Morph (no translation exists between two different units).

Parsed length are postfixed with: em, ex, px, in, cm, mm, pt, pc.

Example:

<div id="foo" style="font-size: 1em">MyDiv</div>
...
Morph("foo", {"style": {"font-size": "2em"}});
element:
An element ID string or a DOM node (see MochiKit.DOM.getElement).
options:
See DefaultOptions.
Availability:
Available in MochiKit 1.4+

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

Portions adapted from Rico are available under the terms of the Apache License, Version 2.0.

Portions adapted from Scriptaculous are available under the terms of the MIT License.

MochiKit-1.4.2/doc/html/MochiKit/Format.html0000660000175000017500000003666311113647640017654 0ustar scottscott MochiKit.Format - string formatting goes here MochiKit Back to docs index

Name

MochiKit.Format - string formatting goes here

Synopsis

assert( truncToFixed(0.12345, 4) == "0.1234" );
assert( roundToFixed(0.12345, 4) == "0.1235" );
assert( twoDigitAverage(1, 0) == "0" );
assert( twoDigitFloat(1.2345) == "1.23" );
assert( twoDigitFloat(1) == "1" );
assert( percentFormat(1.234567) == "123.46%" );
assert( numberFormatter("###,###%")(125) == "12,500%" );
assert( numberFormatter("##.000")(1.25) == "1.250" );

Description

Formatting strings and stringifying numbers is boring, so a couple useful functions in that domain live here.

Dependencies

None.

Overview

Formatting Numbers

MochiKit provides an extensible number formatting facility, modeled loosely after the Number Format Pattern Syntax [1] from Java. numberFormatter(pattern[, placeholder=""[, locale="default"]) returns a function that converts Number to string using the given information. pattern is a string consisting of the following symbols:

Symbol Meaning
- If given, used as the position of the minus sign for negative numbers. If not given, the position to the left of the first number placeholder is used.
# The placeholder for a number that does not imply zero padding.
0 The placeholder for a number that implies zero padding. If it is used to the right of a decimal separator, it implies trailing zeros, otherwise leading zeros.
, The placeholder for a "thousands separator". May be used at most once, and it must be to the left of a decimal separator. Will be replaced by locale.separator in the result (the default is also ,).
. The decimal separator. The quantity of # or 0 after the decimal separator will determine the precision of the result. If no decimal separator is present, the fractional precision is 0 -- meaning that it will be rounded to the nearest integer.
% If present, the number will be multiplied by 100 and the % will be replaced by locale.percent.

API Reference

Functions

formatLocale(locale="default"):

Return a locale object for the given locale. locale may be either a string, which is looked up in the MochiKit.Format.LOCALE object, or a locale object. If no locale is given, LOCALE.default is used (equivalent to LOCALE.en_US).

Availability:
Available in MochiKit 1.3.1+

lstrip(str, chars="\s"):

Returns a string based on str with leading whitespace stripped.

If chars is given, then that expression will be used instead of whitespace. chars should be a string suitable for use in a RegExp [character set].

Availability:
Available in MochiKit 1.3.1+

numberFormatter(pattern, placeholder="", locale="default"):

Return a function formatNumber(aNumber) that formats numbers as a string according to the given pattern, placeholder and locale.

pattern is a string that describes how the numbers should be formatted, for more information see Formatting Numbers.

locale is a string of a known locale (en_US, de_DE, fr_FR, default) or an object with the following fields:

separator The "thousands" separator for this locale (en_US is ",")
decimal The decimal separator for this locale (en_US is ".")
percent The percent symbol for this locale (en_US is "%")
Availability:
Available in MochiKit 1.3.1+

percentFormat(aNumber):

Return a string representation of aNumber * 100, rounded to a maximum precision of 2 fractional digits. Roughly equivalent to: sprintf("%.2f%%", aNumber * 100)

In new code, you probably want to use: numberFormatter("#.##%")(aNumber) instead.

Availability:
Available in MochiKit 1.3.1+

roundToFixed(aNumber, precision):

Return a string representation of aNumber, rounded to precision digits with trailing zeros. This is similar to Number.toFixed(aNumber, precision), but this has implementation consistent rounding behavior (some versions of Safari round 0.5 down!) and also includes preceding 0 for numbers less than 1 (Safari, again).

For example, roundToFixed(0.1357, 2) returns 0.14 on every supported platform, where some return .13 for (0.1357).toFixed(2).

Availability:
Available in MochiKit 1.3.1+

rstrip(str, chars="\s"):

Returns a string based on str with trailing whitespace stripped.

If chars is given, then that expression will be used instead of whitespace. chars should be a string suitable for use in a RegExp [character set].

Availability:
Available in MochiKit 1.3.1+

strip(str, chars="\s"):

Returns a string based on str with leading and trailing whitespace stripped (equivalent to lstrip(rstrip(str, chars), chars)).

If chars is given, then that expression will be used instead of whitespace. chars should be a string suitable for use in a RegExp [character set].

Availability:
Available in MochiKit 1.3.1+

truncToFixed(aNumber, precision):

Return a string representation of aNumber, truncated to precision digits with trailing zeros. This is similar to aNumber.toFixed(precision), but this truncates rather than rounds and has implementation consistent behavior for numbers less than 1. Specifically, truncToFixed(aNumber, precision) will always have a preceding 0 for numbers less than 1.

For example, truncToFixed(0.1357, 2) returns 0.13.

Availability:
Available in MochiKit 1.3.1+

twoDigitAverage(numerator, denominator):

Calculate an average from a numerator and a denominator and return it as a string rounded to a maximum precision of two fractional digits (e.g. "1.23").

If the denominator is 0, "0" will be returned instead of NaN.

Availability:
Available in MochiKit 1.3.1+

twoDigitFloat(aNumber):

Return a string representation of aNumber, rounded to a maximum precision of 2 fractional digits. This is a variation of roundToFixed(aNumber, 2) that removes trailing zeros from the fractional part.

For example, twoDigitFloat(0.1357) returns 0.14 and twoDigitFloat(12.00) returns 12.

In new code, you probably want to use: numberFormatter("#.##")(aNumber) instead.

Availability:
Available in MochiKit 1.3.1+

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/DateTime.html0000660000175000017500000001551311113647640020107 0ustar scottscott MochiKit.DateTime - "what time is it anyway?" MochiKit Back to docs index

Name

MochiKit.DateTime - "what time is it anyway?"

Synopsis

stringDate = toISOTimestamp(new Date());
dateObject = isoTimestamp(stringDate);

Description

Remote servers don't give you JavaScript Date objects, and they certainly don't want them from you, so you need to deal with string representations of dates and timestamps. MochiKit.Date does that.

Dependencies

None.

API Reference

Functions

isoDate(str):

Convert an ISO 8601 date (YYYY-MM-DD) to a Date object.

Availability:
Available in MochiKit 1.3.1+

isoTimestamp(str):

Convert any ISO 8601 [1] timestamp (or something reasonably close to it) to a Date object. Will accept the "de facto" form:

YYYY-MM-DD hh:mm:ss

or (the proper form):

YYYY-MM-DDThh:mm:ssZ

If a time zone designator ("Z" or "[+-]HH:MM") is not present, then the local timezone is used.

Availability:
Available in MochiKit 1.3.1+

toISOTime(date):

Convert a Date object to a string in the form of hh:mm:ss

Availability:
Available in MochiKit 1.3.1+

toISOTimestamp(date, realISO=false):

Convert a Date object to something that's ALMOST but not quite an ISO 8601 [1]_timestamp. If it was a proper ISO timestamp it would be:

YYYY-MM-DDThh:mm:ssZ

However, we see junk in SQL and other places that looks like this:

YYYY-MM-DD hh:mm:ss

So, this function returns the latter form, despite its name, unless you pass true for realISO.

Availability:
Available in MochiKit 1.3.1+

toISODate(date):

Convert a Date object to an ISO 8601 [1] date string (YYYY-MM-DD)

Availability:
Available in MochiKit 1.3.1+

americanDate(str):

Converts a MM/DD/YYYY date to a Date object

Availability:
Available in MochiKit 1.3.1+

toPaddedAmericanDate(date):

Converts a Date object to an MM/DD/YYYY date, e.g. 01/01/2001

Availability:
Available in MochiKit 1.3.1+

toAmericanDate(date):

Converts a Date object to an M/D/YYYY date, e.g. 1/1/2001

Availability:
Available in MochiKit 1.3.1+

See Also

[1](1, 2) W3C profile of ISO 8601: http://www.w3.org/TR/NOTE-datetime

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/LoggingPane.html0000660000175000017500000001542211113647640020604 0ustar scottscott MochiKit.LoggingPane - Interactive MochiKit.Logging pane MochiKit Back to docs index

Name

MochiKit.LoggingPane - Interactive MochiKit.Logging pane

Synopsis

// open a pop-up window
createLoggingPane()
// use a div at the bottom of the document
createLoggingPane(true);

Description

MochiKit.Logging does not have any browser dependencies and is completely unobtrusive. MochiKit.LoggingPane is a browser-based colored viewing pane for your MochiKit.Logging output that can be used as a pop-up or inline.

It also allows for regex and level filtering! MochiKit.LoggingPane is used as the default MochiKit.Logging.debuggingBookmarklet() if it is loaded.

API Reference

Constructors

LoggingPane(inline=false, logger=MochiKit.Logging.logger):

A listener for a MochiKit.Logging logger with an interactive DOM representation.

If inline is true, then the LoggingPane will be a DIV at the bottom of the document. Otherwise, it will be in a pop-up window with a name based on the calling page's URL. If there is an element in the document with an id of _MochiKit_LoggingPane, it will be used instead of appending a new DIV to the body.

logger is the reference to the MochiKit.Logging.Logger to listen to. If not specified, the global default logger is used.

Properties:

win:
Reference to the pop-up window (undefined if inline)
inline:
true if the LoggingPane is inline
colorTable:

An object with property->value mappings for each log level and its color. May also be mutated on LoggingPane.prototype to affect all instances. For example:

MochiKit.LoggingPane.LoggingPane.prototype.colorTable = {
    DEBUG: "green",
    INFO: "black",
    WARNING: "blue",
    ERROR: "red",
    FATAL: "darkred"
};
Availability:
Available in MochiKit 1.3.1+

LoggingPane.prototype.closePane():

Close the LoggingPane (close the child window, or remove the _MochiKit_LoggingPane DIV from the document).

Availability:
Available in MochiKit 1.3.1+

Functions

createLoggingPane(inline=false):

Create or return an existing LoggingPane for this document with the given inline setting. This is preferred over using LoggingPane directly, as only one LoggingPane should be present in a given document.

Availability:
Available in MochiKit 1.3.1+

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Position.html0000660000175000017500000000346711113647640020224 0ustar scottscott MochiKit.Position - DOM Position manipulation API MochiKit Back to docs index

Name

MochiKit.Position - DOM Position manipulation API

Synopsis

This module is experimental and is present in MochiKit 1.4+ only. No functions are currently exported from this module. Documentation is forthcoming.

Copyright

Copyright 2005-2006 Bob Ippolito <bob@redivi.com>, and others. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/DOM.html0000660000175000017500000020423411113647640017032 0ustar scottscott MochiKit.DOM - painless DOM manipulation API MochiKit Back to docs index

Name

MochiKit.DOM - painless DOM manipulation API

Synopsis

var rows = [
    ["dataA1", "dataA2", "dataA3"],
    ["dataB1", "dataB2", "dataB3"]
];
row_display = function (row) {
    return TR(null, map(partial(TD, null), row));
}
var newTable = TABLE({'class': 'prettytable'},
    THEAD(null,
        row_display(["head1", "head2", "head3"])),
    TFOOT(null,
        row_display(["foot1", "foot2", "foot3"])),
    TBODY(null,
        map(row_display, rows)));
// put that in your document.createElement and smoke it!
swapDOM(oldTable, newTable);

Description

As you probably know, the DOM APIs are some of the most painful Java-inspired APIs you'll run across from a highly dynamic language. Don't worry about that though, because they provide a reasonable basis to build something that sucks a lot less.

MochiKit.DOM takes much of its inspiration from Nevow's [1] stan [2]. This means you choose a tag, give it some attributes, then stuff it full of whatever objects you want. MochiKit.DOM isn't stupid, it knows that a string should be a text node, and that you want functions to be called, and that Array-like objects should be expanded, and stupid null values should be skipped.

Hell, it will let you return strings from functions, and use iterators from MochiKit.Iter. If that's not enough, just teach it new tricks with registerDOMConverter. If you have never used an API like this for creating DOM elements, you've been wasting your damn time. Get with it!

Dependencies

Overview

DOM Coercion Rules

In order of precedence, createDOM coerces given arguments to DOM nodes using the following rules:

  1. Functions are called with a this and first argument of the parent node and their return value is subject to the following rules (even this one).
  2. undefined and null are ignored.
  3. If MochiKit.Iter is loaded, iterables are flattened (as if they were passed in-line as nodes) and each return value is subject to these rules.
  4. Values that look like DOM nodes (objects with a .nodeType > 0) are .appendChild'ed to the created DOM fragment.
  5. Strings are wrapped up with document.createTextNode
  6. Objects that have a .dom(node) or .__dom__(node) method are called with the parent node and their result is coerced using these rules. (MochiKit 1.4+).
  7. Objects that are not strings are run through the domConverters MochiKit.Base.AdapterRegistry (see registerDOMConverter). The adapted value is subject to these same rules (e.g. if the adapter returns a string, it will be coerced to a text node).
  8. If no adapter is available, .toString() is used to create a text node.

Creating DOM Element Trees

createDOM provides you with an excellent facility for creating DOM trees that is easy on the wrists. One of the best ways to understand how to use it is to take a look at an example:

var rows = [
    ["dataA1", "dataA2", "dataA3"],
    ["dataB1", "dataB2", "dataB3"]
];
row_display = function (row) {
    return TR(null, map(partial(TD, null), row));
}
var newTable = TABLE({'class': 'prettytable'},
    THEAD(null,
        row_display(["head1", "head2", "head3"])),
    TFOOT(null,
        row_display(["foot1", "foot2", "foot3"])),
    TBODY(null,
        map(row_display, rows)));

This will create a table with the following visual layout (if it were inserted into the document DOM):

head1 head2 head3
dataA1 dataA2 dataA3
dataB1 dataB2 dataB3
foot1 foot2 foot3

Corresponding to the following HTML:

<table class="prettytable">
    <thead>
        <tr>
            <td>head1</td>
            <td>head2</td>
            <td>head3</td>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <td>foot1</td>
            <td>foot2</td>
            <td>foot3</td>
        </tr>
    </tfoot>
    <tbody>
        <tr>
            <td>dataA1</td>
            <td>dataA2</td>
            <td>dataA3</td>
        </tr>
        <tr>
            <td>dataB1</td>
            <td>dataB2</td>
            <td>dataB3</td>
        </tr>
    </tbody>
</table>

DOM Context

In order to prevent having to pass a window and/or document variable to every MochiKit.DOM function (e.g. when working with a child window), MochiKit.DOM maintains a context variable for each of them. They are managed with the withWindow and withDocument functions, and can be acquired with currentWindow() and currentDocument()

For example, if you are creating DOM nodes in a child window, you could do something like this:

withWindow(child, function () {
    var doc = currentDocument();
    appendChildNodes(doc.body, H1(null, "This is in the child!"));
});

Note that withWindow(win, ...) also implies withDocument(win.document, ...).

DOM Gotchas

Performance Tradeoff:
DOM is much easier to get correct and more flexible than working directly with markup as strings. Modifying innerHTML is still the fastest way to make document changes.
Internet Explorer:
Internet Explorer's DOM implementation is quite poor in comparison to the other popular implementations. In order to avoid memory leaks due to circular references, you should use MochiKit.Signal.connect for all of your event handling needs. Additionally, when creating tables with DOM, it is required to use a TBODY tag (see Creating DOM Element Trees for an example of this).

API Reference

Functions

$(id[, ...]):

An alias for getElement(id[, ...])

Availability:
Available in MochiKit 1.3.1+

addElementClass(element, className):

Ensure that the given element has className set as part of its class attribute. This will not disturb other class names. element is looked up with getElement, so string identifiers are also acceptable.

Availability:
Available in MochiKit 1.3.1+

addLoadEvent(func):

Note that addLoadEvent can not be used in combination with MochiKit.Signal if the onload event is connected. Once an event is connected with MochiKit.Signal, no other APIs may be used for that same event.

This will stack window.onload functions on top of each other. Each function added will be called after onload in the order that they were added.

Availability:
Available in MochiKit 1.3.1+

addToCallStack(target, path, func[, once]):

Note that addToCallStack is not compatible with MochiKit.Signal. Once an event is connected with MochiKit.Signal, no other APIs may be used for that same event.

Set the property path of target to a function that calls the existing function at that property (if any), then calls func.

If target[path]() returns exactly false, then func will not be called.

If once is true, then target[path] is set to null after the function call stack has completed.

If called several times for the same target[path], it will create a stack of functions (instead of just a pair).

Availability:
Available in MochiKit 1.3.1+

appendChildNodes(node[, childNode[, ...]]):

Append children to a DOM element using the DOM Coercion Rules.

node:
A reference to the DOM element to add children to (if a string is given, getElement(node) will be used to locate the node)
childNode...:
All additional arguments, if any, will be coerced into DOM nodes that are appended as children using the DOM Coercion Rules.
returns:
The given DOM element
Availability:
Available in MochiKit 1.3.1+

insertSiblingNodesBefore(node[, siblingNode[, ...]]):

Insert children into the DOM structure using the DOM Coercion Rules.

node:
A reference to the DOM element you want to insert children before (if a string is given, getElement(node) will be used to locate the node)
siblingNode...:
All additional arguments, if any, will be coerced into DOM nodes that are inserted as siblings using the DOM Coercion Rules.
returns:
The parent of the given DOM element
Availability:
Available in MochiKit 1.4+

insertSiblingNodesAfter(node[, siblingNode[, ...]]):

Insert children into the DOM structure using the DOM Coercion Rules.

node:
A reference to the DOM element you want to insert children after (if a string is given, getElement(node) will be used to locate the node)
siblingNode...:
All additional arguments, if any, will be coerced into DOM nodes that are inserted as siblings using the DOM Coercion Rules.
returns:
The parent of the given DOM element
Availability:
Available in MochiKit 1.4+

createDOM(name[, attrs[, node[, ...]]]):

Create a DOM fragment in a really convenient manner, much like Nevow`s [1] stan [2].

Partially applied versions of this function for common tags are available as aliases:

  • A
  • BUTTON
  • BR
  • CANVAS
  • DD
  • DIV
  • DL
  • DT
  • FIELDSET
  • FORM
  • H1
  • H2
  • H3
  • H4
  • H5
  • H6
  • HR
  • IMG
  • INPUT
  • LABEL
  • LEGEND
  • LI
  • OL
  • OPTGROUP
  • OPTION
  • P
  • PRE
  • SELECT
  • SPAN
  • STRONG
  • TABLE
  • TBODY
  • TD
  • TEXTAREA
  • TFOOT
  • TH
  • THEAD
  • TR
  • TT
  • UL

See Creating DOM Element Trees for a comprehensive example.

name:
The kind of fragment to create (e.g. 'span'), such as you would pass to document.createElement.
attrs:

An object whose properties will be used as the attributes (e.g. {'style': 'display:block'}), or null if no attributes need to be set.

See updateNodeAttributes for more information.

For convenience, if attrs is a string, null is used and the string will be considered the first node.

node...:
All additional arguments, if any, will be coerced into DOM nodes that are appended as children using the DOM Coercion Rules.
returns:
A DOM element
Availability:
Available in MochiKit 1.3.1+

createDOMFunc(tag[, attrs[, node[, ...]]]):

Convenience function to create a partially applied createDOM function. You'd want to use this if you add additional convenience functions for creating tags, or if you find yourself creating a lot of tags with a bunch of the same attributes or contents.

See createDOM for more detailed descriptions of the arguments.

tag:
The name of the tag
attrs:
Optionally specify the attributes to apply
node...:
Optionally specify any children nodes it should have
returns:
function that takes additional arguments and calls createDOM
Availability:
Available in MochiKit 1.3.1+

currentDocument():

Return the current document DOM Context. This will always be the same as the global document unless withDocument or withWindow is currently executing.

Availability:
Available in MochiKit 1.3.1+

currentWindow():

Return the current window DOM Context. This will always be the same as the global window unless withWindow is currently executing.

Availability:
Available in MochiKit 1.3.1+

emitHTML(dom[, lst]):

Convert a DOM tree to an Array of HTML string fragments. This should be used for debugging/testing purposes only.

The DOM property innerHTML or cloneNode(true) method should be used for most purposes.

Availability:
Available in MochiKit 1.3.1+

escapeHTML(s):

Make a string safe for HTML, converting the usual suspects (<, >, ", &) to their HTML character entity equivalents.

Availability:
Available in MochiKit 1.3.1+

focusOnLoad(element):

Note that focusOnLoad can not be used in combination with MochiKit.Signal if the onload event is connected. Once an event is connected with MochiKit.Signal, no other APIs may be used for that same event.

This adds an onload event to focus the given element.

Availability:
Available in MochiKit 1.3.1+

formContents(elem=document.body):

Search the DOM tree, starting at elem, for any elements with a name and value attribute. Return a 2-element Array of names and values suitable for use with MochiKit.Base.queryString.

Availability:
Available in MochiKit 1.3.1+

getElement(id[, ...]):

A small quick little function to encapsulate the getElementById method. It includes a check to ensure we can use that method.

If the id isn't a string, it will be returned as-is.

Also available as $(...) for convenience and compatibility with other JavaScript frameworks.

If multiple arguments are given, an Array will be returned.

Availability:
Available in MochiKit 1.3.1+

getElementsByTagAndClassName(tagName, className, parent=document):

Returns an array of elements in parent that match the tag name and class name provided. If parent is a string, it will be looked up with getElement.

If tagName is null or "*", all elements will be searched for the matching class.

If className is null, all elements matching the provided tag are returned.

Availability:
Available in MochiKit 1.3.1+

getFirstElementByTagAndClassName(tagName, className, parent=document):

Return the first element in parent that matches the tag name and class name provided. If parent is a string, it will be looked up with getElement.

If tagName is null or "*", all elements will be searched for the matching class.

If className is null, the first element matching the provided tag will be returned.

Availability:
Available in MochiKit 1.4+

getFirstParentByTagAndClassName(elem, tagName='*', className=null):

Returns the first parent of elem that matches the tag name and class name provided. If elem is a string, it will be looked up using getElement.

If tagName is null or "*", all elements will be searched for the matching class.

If className is null, the first element matching the provided tag name will be returned.

If no match is found, null will be returned.

Availability:
Available in MochiKit 1.4+

getNodeAttribute(node, attr):

Get the value of the given attribute for a DOM element without ever raising an exception (will return null on exception).

node:
A reference to the DOM element to update (if a string is given, getElement(node) will be used to locate the node)
attr:

The name of the attribute

Note that it will do the right thing for IE, so don't do the class -> className hack yourself.

returns:
The attribute's value, or null
Availability:
Available in MochiKit 1.3.1+

hasElementClass(element, className[, ...]):

Return true if className is found on the element. element is looked up with getElement, so string identifiers are also acceptable.

Availability:
Available in MochiKit 1.3.1+

isChildNode(node, maybeParent):

Determine whether node is a child node or decendant node of maybeParent. Returns true if so, and false if not. A node is considered a child node of itself for the purposes of this function.

If either node or maybeParent are strings, the related nodes will be looked up with getElement.

Availability:
Available in MochiKit 1.4+

registerDOMConverter(name, check, wrap[, override]):

Register an adapter to convert objects that match check(obj, ctx) to a DOM element, or something that can be converted to a DOM element (i.e. number, bool, string, function, iterable).

Availability:
Available in MochiKit 1.3.1+

removeElement(node):

Remove and return node from a DOM tree.

node:
the DOM element (or string id of one) to be removed
returns
The removed element
Availability:
Available in MochiKit 1.3.1+

removeElementClass(element, className):

Ensure that the given element does not have className set as part of its class attribute. This will not disturb other class names. element is looked up with getElement, so string identifiers are also acceptable.

Availability:
Available in MochiKit 1.3.1+

removeEmptyTextNodes(node):

Remove all text node children that contain only whitespace from node. Useful in situations where such empty text nodes can interfere with DOM traversal.

node:
the DOM element (or string id of one) to remove whitespace child nodes from.
Availability:
Available in MochiKit 1.4+

replaceChildNodes(node[, childNode[, ...]]):

Remove all children from the given DOM element, then append any given childNodes to it (by calling appendChildNodes).

node:
A reference to the DOM element to add children to (if a string is given, getElement(node) will be used to locate the node)
childNode...:
All additional arguments, if any, will be coerced into DOM nodes that are appended as children using the DOM Coercion Rules.
returns:
The given DOM element
Availability:
Available in MochiKit 1.3.1+

scrapeText(node[, asArray=false]):

Walk a DOM tree in-order and scrape all of the text out of it as a string.

If asArray is true, then an Array will be returned with each individual text node. These two are equivalent:

assert( scrapeText(node) == scrapeText(node, true).join("") );
Availability:
Available in MochiKit 1.3.1+

setElementClass(element, className):

Set the entire class attribute of element to className. element is looked up with getElement, so string identifiers are also acceptable.

Availability:
Available in MochiKit 1.3.1+

setNodeAttribute(node, attr, value):

Set the value of the given attribute for a DOM element without ever raising an exception (will return null on exception). If setting more than one attribute, you should use updateNodeAttributes.

node:
A reference to the DOM element to update (if a string is given, getElement(node) will be used to locate the node)
attr:

The name of the attribute

Note that it will do the right thing for IE, so don't do the class -> className hack yourself.

Also note that the DOM element object property with the same name will also be set if not already identical to the attribute value. This is needed to compensate for weird attributes that distinguish between the property and attribute values (i.e. the "value" attribute for fields).

value:
The value of the attribute, may be an object to be merged (e.g. for setting style).
returns:
The given DOM element or null on failure
Availability:
Available in MochiKit 1.3.1+

swapDOM(dest, src):

Replace dest in a DOM tree with src, returning src.

dest:
a DOM element (or string id of one) to be replaced
src:
the DOM element (or string id of one) to replace it with, or null if dest is to be removed (replaced with nothing).
returns:
a DOM element (src)
Availability:
Available in MochiKit 1.3.1+

swapElementClass(element, fromClass, toClass):

If fromClass is set on element, replace it with toClass. This will not disturb other classes on that element. element is looked up with getElement, so string identifiers are also acceptable.

Availability:
Available in MochiKit 1.3.1+

toggleElementClass(className[, element[, ...]]):

Toggle the presence of a given className in the class attribute of all given elements. All elements will be looked up with getElement, so string identifiers are acceptable.

Availability:
Available in MochiKit 1.3.1+

toHTML(dom):

Convert a DOM tree to a HTML string using emitHTML. This should be used for debugging/testing purposes only.

The DOM property innerHTML or cloneNode(true) method should be used for most purposes.

Availability:
Available in MochiKit 1.3.1+

updateNodeAttributes(node, attrs):

Update the attributes of a DOM element from a given object.

node:
A reference to the DOM element to update (if a string is given, getElement(node) will be used to locate the node)
attrs:

An object whose properties will be used to set the attributes (e.g. {'class': 'invisible'}), or null if no attributes need to be set. If an object is given for the attribute value (e.g. {'style': {'display': 'block'}}) then MochiKit.Base.updatetree will be used to set that attribute.

Note that it will do the right thing for IE, so don't do the class -> className hack yourself, and it deals with setting "on..." event handlers correctly.

Also note that the DOM element object property with the same name will also be set if not already identical to the attribute value. This is needed to compensate for weird attributes that distinguish between the property and attribute values (i.e. the "value" attribute for fields).

returns:
The given DOM element
Availability:
Available in MochiKit 1.3.1+

withWindow(win, func):

Call func with the window DOM Context set to win and the document DOM Context set to win.document. When func() returns or throws an error, the DOM Context will be restored to its previous state.

The return value of func() is returned by this function.

Availability:
Available in MochiKit 1.3.1+

withDocument(doc, func):

Call func with the doc DOM Context set to doc. When func() returns or throws an error, the DOM Context will be restored to its previous state.

The return value of func() is returned by this function.

Availability:
Available in MochiKit 1.3.1+

Style Functions

These functions were previously available in MochiKit.DOM, but have been moved to MochiKit.Style in recent versions. Function aliases remain for backwards compability.

computedStyle(htmlElement, cssProperty, mozillaEquivalentCSS):

Looks up a CSS property for the given element. The element can be specified as either a string with the element's ID or the element object itself.

cssProperty:
MochiKit 1.3.1 expects camel case, e.g. backgroundColor. MochiKit 1.4+ expects CSS selector case, e.g. background-color, but will accept camel case for backwards-compatibility.
mozillaEquivalentCSS:
MochiKit 1.3.1 expects selector case. MochiKit 1.4+ ignores this argument.
Availability:
Available in MochiKit 1.3.1, deprecated in favor of MochiKit.Style.getStyle in 1.4+

elementDimensions(element):

Return the absolute pixel width and height (including padding and border, but not margins) of element as an object with w and h properties, or undefined if element is not in the document. element may be specified as a string to be looked up with getElement, a DOM element, or trivially as an object with w and/or h properties.

Availability:
Available in MochiKit 1.3.1, deprecated in favor of MochiKit.Style.getElementDimensions in 1.4+

elementPosition(element[, relativeTo={x: 0, y: 0}]):

Return the absolute pixel position of element in the document as an object with x and y properties, or undefined if element is not in the document. element may be specified as a string to be looked up with getElement, a DOM element, or trivially as an object with x and/or y properties.

If relativeTo is given, then its coordinates are subtracted from the absolute position of element, e.g.:

var elemPos = elementPosition(elem);
var anotherElemPos = elementPosition(anotherElem);
var relPos = elementPosition(elem, anotherElem);
assert( relPos.x == (elemPos.x - anotherElemPos.x) );
assert( relPos.y == (elemPos.y - anotherElemPos.y) );

relativeTo may be specified as a string to be looked up with getElement, a DOM element, or trivially as an object with x and/or y properties.

Availability:
Available in MochiKit 1.3.1, deprecated in favor of MochiKit.Style.getElementPosition in 1.4+

getViewportDimensions():

Return the pixel width and height of the viewport as an object with w and h properties. element is looked up with getElement, so string identifiers are also acceptable.

Availability:
Available in MochiKit 1.3.1, moved to MochiKit.Style.getViewportDimensions in 1.4+

hideElement(element, ...):

Partial form of setDisplayForElement, specifically:

partial(setDisplayForElement, "none")

For information about the caveats of using a style.display based show/hide mechanism, and a CSS based alternative, see Element Visibility.

Availability:
Available in MochiKit 1.3.1, moved to MochiKit.Style.hideElement in 1.4+

makeClipping(element):

Ensure that element.style.overflow = 'hidden'. If element is a string, then it will be looked up with getElement.

Returns the original values of overflow, overflow-y and overflow-y so that they may be restored with undoClipping(element, overflow).

Availability:
Available in MochiKit 1.4+, moved to MochiKit.Style.makeClipping in 1.4.1+

makePositioned(element):

Ensure that element.style.position is set to "relative" if it is not set or is "static". If element is a string, then it will be looked up with getElement.

Availability:
Available in MochiKit 1.4+, moved to MochiKit.Style.makePositioned in 1.4.1+

setElementDimensions(element, dimensions[, units='px']):

Sets the dimensions of element in the document from an object with w and h properties.

node:
A reference to the DOM element to update (if a string is given, getElement(node) will be used to locate the node)
dimensions:
An object with w and h properties
units:
Optionally set the units to use, default is px
Availability:
Available in MochiKit 1.3.1, moved to MochiKit.Style.setElementDimensions in 1.4+

setElementPosition(element, position[, units='px']):

Sets the absolute position of element in the document from an object with x and y properties.

node:
A reference to the DOM element to update (if a string is given, getElement(node) will be used to locate the node)
position:
An object with x and y properties
units:
Optionally set the units to use, default is px
Availability:
Available in MochiKit 1.3.1, moved to MochiKit.Style.setElementPosition in 1.4+

setDisplayForElement(display, element[, ...]):

Change the style.display for the given element(s). Usually used as the partial forms:

Elements are looked up with getElement, so string identifiers are acceptable.

For information about the caveats of using a style.display based show/hide mechanism, and a CSS based alternative, see Element Visibility.

Availability:
Available in MochiKit 1.3.1, moved to MochiKit.Style.setDisplayForElement in 1.4+

setOpacity(element, opacity):

Sets opacity for element. Valid opacity values range from 0 (invisible) to 1 (opaque). element is looked up with getElement, so string identifiers are also acceptable.

Availability:
Available in MochiKit 1.3.1, moved to MochiKit.Style.setOpacity in 1.4+

showElement(element, ...):

Partial form of setDisplayForElement, specifically:

partial(setDisplayForElement, "block")

For information about the caveats of using a style.display based show/hide mechanism, and a CSS based alternative, see Element Visibility.

Availability:
Available in MochiKit 1.3.1, moved to MochiKit.Style.showElement in 1.4+

undoClipping(element, overflow):

Restore the setting of element.style.overflow set by makeClipping(element). If element is a string, then it will be looked up with getElement.

Availability:
Available in MochiKit 1.4+, moved to MochiKit.Style.undoClipping in 1.4.1+

undoPositioned(element):

Restore the setting of element.style.position set by makePositioned(element). If element is a string, then it will be looked up with getElement.

Availability:
Available in MochiKit 1.4+, moved to MochiKit.Style.undoPositioned in 1.4.1+

Style Objects

These objects are available in MochiKit 1.3.1, but have been moved to MochiKit.Style in 1.4+.

Coordinates(x, y):

Constructs an object with x and y properties. obj.toString() returns something like {x: 0, y: 42} for debugging.

Availability: Available in MochiKit 1.3.1, moved to MochiKit.Style.Coordinates in 1.4+

Dimensions(w, h):

Constructs an object with w and h properties. obj.toString() returns something like {w: 0, h: 42} for debugging.

Availability: Available in MochiKit 1.3.1, moved to MochiKit.Style.Dimensions in 1.4+

See Also

[1](1, 2) Nevow, a web application construction kit for Python: http://divmod.org/trac/wiki/DivmodNevow
[2](1, 2) nevow.stan is a domain specific language for Python (read as "crazy getitem/call overloading abuse") that Donovan and I schemed up at PyCon 2003 at this super ninja Python/C++ programmer's (David Abrahams) hotel room. Donovan later inflicted this upon the masses in Nevow. Check out the Nevow Guide for some examples: http://divmod.org/trac/wiki/DivmodNevow

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Selector.html0000660000175000017500000003376411113647640020203 0ustar scottscott MochiKit.Selector - Selecting elements by CSS selector syntax MochiKit Back to docs index

Name

MochiKit.Selector - Selecting elements by CSS selector syntax

Synopsis

MochiKit.Base.map(MochiKit.Visual.fade, $$('p.fademe'));

Description

MochiKit.Selector provides utilities to select elements by CSS selector syntax. In particular it provides the $$ function.

Overview

This module provides facilities to select childs of a DOM node by using CSS selector syntax. In particular, it provides the $$ function, which performs such a selection on the current document.

Many of CSS3 [1] selectors are supported:

  • Select by tag name (A)

  • Select by class (.theclass)

  • Select by id (#someid)

  • Combinators
    • Descendant: E F
    • Child: E > F
    • Immediate following sibling: E + F
    • Following sibling: E ~ F
  • Attribute selectors
    • simple "has attribute" (without operator)
    • = equal
    • != not equal (not in CSS std.)
    • ~= word containment
    • ^= starts-with
    • $= ends-with
    • *= substring containment
    • |= first part of hyphen deleimited (eg. lang|="en" matches lang="en-US")
  • Pseudo-classes
    • :nth-child, :nth-last-child, :first-child, :last-child, :only-child, :empty, :enabled, :disabled, :checked, :not(<any other selector>)
  • Deprecated Pseudo-classes (to be removed in 1.5)
    • :root, :nth-of-type, :nth-last-of-type, :first-of-type, :last-of-type, :only-of-type

Multiple selectors can be concatenated, like this: P.quote[author~='Torvalds'], in which case elements matching all the selectors are returned. Furthermore, such concatenations can be combined by joining them with spaces and combinators. This invokes the regular CSS behaviour of matching parts of the combination in sequence, starting off each part from the elements returned by the preceeding part.

For the :nth-* pseudoclasses, the an+b syntax is partially supported, specifically a and b must be non-negative and only a is optional (this differs from the CSS std.) Also, odd and even are supported, e.g. table tr:nth-child(odd) gives you every other row of table starting with the first one.

For further documentation of CSS selectors, refer to the W3C CSS standard. [1]

The original version of this module was ported from Prototype.

Note: This module is currently experimental and API stability cannot be fully guaranteed. The implementation is scheduled to be replaced with a new faster version (now in development) during the MochiKit 1.5 development cycle.

Note: Due to how Internet Explorer handles node attributes, some attribute selectors may not work as expected. In particular a[title] will not work as all A elements in the Internet Explorer DOM model have a title attribute regardless of whether it's specified in the markup or not.

API Reference

Functions

findDocElements(expression[, ...]):

Performs a selection on the active document. Equivalent to findChildElements(MochiKit.DOM.currentDocument(), [expression, ...])

Availability:
Available in MochiKit 1.4+

findChildElements(element, expressions):

Traverses the child nodes of element and returns the subset of those that match any of the selector expressions in expressions.

Each expression can be a combination of simple expressions, by concatenating them with spaces or combinators. In that case, normal CSS rules apply, each simple expression is evaluated in turn and the results of that one is used as the scope for the succeeding expression (see Selector.findElements). Finally, the results of the last simple expression is returned as the search result.

Availability:
Available in MochiKit 1.4+

$$(expression[, ...]):

An alias to findDocElements.

Availability:
Available in MochiKit 1.4+

Constructors

Selector(simpleExpression):

An object storing the parsed version of a simple CSS selector expression and providing functions for executing searches.

Simple means that the expression is not a combination of expressions, i.e. it does not contain any spaces.

Usually the user would not instantiate or use this object directly, but heres how:

var selector = new MochiKit.Selector.Selector('#someelementid');
var searchResults = selector.findElements(rootElement);
Deprecated:
Use findChildElements instead. The Selector class will be removed in version 1.5.
Availability:
Available in MochiKit 1.4+

Selector.findElements(scope[, axis=""]):

Performs a search on scope. The value of axis controls what relatives of scope are considered.

scope:
A DOM node that acts as a starting point for the search.
axis:
One of ">", "+", "~" or the empty string (default). If the empty string, all descendant nodes of scope are tested against the expression. If > only direct child nodes of scope are tested, if + only the next sibling (if any) of scope is tested and if ~ all succeeding siblings of scope are tested.
Deprecated:
Use findChildElements instead. The Selector class will be removed in version 1.5.
Availability:
Available in MochiKit 1.4+

See Also

[1](1, 2) CSS Selectors Level 3 (Last Call, oct. 2006): http://www.w3.org/TR/2005/WD-css3-selectors-20051215/

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

Based on Prototype, (c) 2005 Sam Stephenson, available under the Prototype license

MochiKit-1.4.2/doc/html/MochiKit/DragAndDrop.html0000660000175000017500000002407011113647640020536 0ustar scottscott MochiKit.DragAndDrop - drag and drop elements with MochiKit MochiKit Back to docs index

Name

MochiKit.DragAndDrop - drag and drop elements with MochiKit

Synopsis

// Create a draggable
new Draggable('mydrag');

// Create a corresponding droppable
new Droppable('mydrop', {
    accept: ['drag-class'],
    ondrop: function (element) {
        alert('"' + element.id + '" was dropped on me');
    }
});

Description

MochiKit.DragAndDrop enables you the power of dragging elements through your pages, for richer interfaces.

Overview

The implementation was adapted from Scriptaculous.

API Reference

Constructors

Draggable(element[, options]):

A object that can be drag with the mouse.

You have the following options, with corresponding default values:

handle (false):
Option for giving the element where starting the drag. By default it's the element itself, but you can either put a class of a subelement or the id of another element as handle.
starteffect (MochiKit.Visual.Opacity):
Function called once the drag has begun, taking the dragged element as argument. It's an effect by default but you can define any callback.
reverteffect (MochiKit.Visual.Move):
Effect applied when drag is cancelled. You have to define the revert option to enable the call. By default it brings the element back to its initial position, so you should know what you want when you modify this. The function should return an effect that can be cancelled.
endeffect (MochiKit.Visual.Opacity):
Pending part of starteffect. If you have modified your element during start, you'd usually want to revert it in the function.
zindex (1000):
Zindex of the drag element. By default it brings it to front.
revert (false):
Indicate if the reverteffect function should be called. If you define a function here, this function will be called before reverteffect, with the element as first argument.
snap (false):
Define the behaviour of the drag element when moving. It can either be a function, a value or an array of two values. If it's a function, it should take the (x, y) position of the element as arguments, and return the position draw in the browser. If its a value, it's used as a modulo for each coordinates. If it's an array, each value is applied for the corresponding coordinate.
selectclass (null):
If defined, name of CSS class applied during the drag.
ghosting (null):
Make a ghost from the draggable: clone it at start, then remove the clone at end.
onchange  (MochiKit.Base.noop):
Function called when updates are made on the draggable object.
scroll (false):
Element to scroll around, if precised. For example, window will allow the draggable to scroll in the page.
scrollSensitivity (20):
Scroll sensitivity, used when scroll is used.
scrollSpeed (15):
Scroll speed, used when scroll is used.

A draggable generates some signals during its lifetime: start, drag and end. They are available through the Draggables handler, and are called with a draggable as argument. You can register a callback for these events like this:

onStart = function (draggable) {
    // Do some stuff
};

connect(Draggables, 'start', onStart);
Availability:
Available in MochiKit 1.4+

Droppable(element[, options]):

A object where you can drop a draggable.

You have the following options, with corresponding default values:

greedy (true):
Stop on this droppable when a draggable drops over it.
hoverclass (null):
If defined, name of CSS class applied when a draggable is hover the droppable element (hover state).
hoverfunc (MochiKit.Base.noop):
Function called on hover state.
accept (null):
Array of CSS classes allowed to drop on this.
activeclass (null):
If defined, name of CSS class applied if a possible draggable begins its start (active state).
onactive (MochiKit.Base.noop):
Function called on active state.
containment ([]):
Specify a list of elements to check for active state: only the children of the specified elements can be dropped. Mainly useful for Sortable.
onhover (MochiKit.Base.noop):
Specific hover function, mainly used for Sortable.
ondrop (MochiKit.Base.noop):
Function called when a draggable is dropped. The function takes three arguments: the draggable element, the droppable element, and the event that raised the drop.
Availability:
Available in MochiKit 1.4+

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

Portions adapted from Scriptaculous are available under the terms of the MIT License.

MochiKit-1.4.2/doc/html/MochiKit/index.html0000660000175000017500000006314611113647640017527 0ustar scottscott MochiKit Documentation Index MochiKit

Distribution

MochiKit - makes JavaScript suck a bit less

Notes

To turn off MochiKit's export feature (which may be necessary for compatibility with some existing code), do this before loading MochiKit:

<script type="text/javascript">MochiKit = {__export__: false};</script>

When export mode is off, you must use fully qualified names for all MochiKit functions (e.g. MochiKit.Base.map(...)).

See Also

Version History

2008-11-27 v1.4.2 (bug fix release)

  • Changed default packed version to contain all modules (since easy customization is now available).
  • More fixes in MochiKit.Style.getElementDimensions for IE and hidden elements (#325).
  • Fixed issue in MochiKit.Style.getViewportDimensions when called within the document HEAD.
  • Fixed MochiKit.DOM.coerceToDOM() handling of arrays when MochiKit.Iter is not loaded (#328).

2008-11-02 v1.4.1 (bug fix release)

  • Added export of deprecated MochiKit.DOM.computedStyle function (#324).
  • Fixed issue in MochiKit.Style.getElementDimensions when elements are hidden due to CSS class definitions (#325).
  • Moved makePositioned, undoPositioned, makeClipping and undoClipping from MochiKit.DOM to MochiKit.Style due to circular dependency (#327).
  • Fixed makeClipping and undoClipping to handle overflow-x and overflow-y styles correctly (#326).
  • Fixed issue with Event.relatedTarget() sometimes returning XUL elements in Mozilla-based browsers (#322).

2008-10-21 v1.4

  • Added pt_BR to MochiKit.Format.LOCALE.
  • MochiKit.Async now sets the "X-Requested-With: XMLHttpRequest" header, a de facto standard (Prototype, jQuery, Mootools).
  • MochiKit.Signal custom handlers no longer cause callbacks to get re-bound to the source if they were previously bound.
  • Fixed MochiKit.Signal.signal re-entrancy bug that could cause recently disconnected slots to get signaled.
  • MochiKit.Base.evalJSON will now evaluate JSON that is wrapped in a /* comment block */.
  • MochiKit.Color's HSV to RGB conversion code fixed to return the correct value (hsv.v for RGB values) in cases where saturation === 0.
  • doXHR workaround for a Mozilla bug when calling XMLHttpRequest in certain situations. Always wraps call in a callLater(0, doXHR, url, opts).
  • parseQueryString will now parse values with embedded "="
  • Workaround for a Safari DOM crash when using MochiKit.Iter.list. http://bugs.webkit.org/show_bug.cgi?id=12191
  • New removeNodeAttribute function in MochiKit.DOM.
  • MochiKit.Async.doXHR and dependent functions now accept 201 CREATED and 204 NO CONTENT as valid.
  • MochiKit.DOM.formContents now treats option tags the same way that form posts do in the case of missing and empty string value attributes, even in IE.
  • MochiKit.Base.queryString now accepts third queryString([names, values]) form.
  • MochiKit.DOM.formContents now defaults to document.body if no element is given.
  • New MochiKit.Selector module (still somewhat experimental)
  • MochiKit.LoggingPane fixes for Internet Explorer
  • MochiKit.DOM now creates XHTML nodes in XUL documents.
  • MochiKit.LoggingPane now works on pages with '#' in the URL on IE
  • New MochiKit.Async.doXHR as a convenient method for doing custom XMLHttpRequests (e.g. extra headers, overrideMimeType, etc.)
  • New __connect__ protocol for MochiKit.Signal.connect source notifications
  • Added colSpan, bgColor to the list of DOM renames for Internet Explorer
  • New MochiKit.Signal.disconnectAllTo function
  • MochiKit.Base.parseQueryString now accepts leading question mark
  • New MochiKit.Base.values function
  • Fixed MochiKit.Signal.disconnect when called from a signal handler invoked by MochiKit.Signal.signal
  • parseQueryString now splits on HTML entities equivalent to ampersand as well
  • Better XHTML compatibility (removed obvious cases where uppercase tagName or nodeName was assumed)
  • MochiKit.Base.queryString now handles array values in the same way HTML forms handle multiple elements of the same name.
  • MochiKit.Base.parseQueryString now returns {} for empty query string instead of {"": "undefined"}
  • MochiKit.DOM.formContents now handles option value="" correctly.
  • MochiKit.DOM now checks for undefined className.
  • MochiKit.Iter.groupby() now uses compare() to group rather than == and !=
  • serializeJSON no longer serializes undefined, as per the JSON spec
  • Fixed an infinite recursion bug in serializeJSON if an adapter returns the object itself.
  • Fixed vertical tab and control char encoding in serializeJSON (#313).
  • New MochiKit.Base.operator.seq and sne to support strict comparison
  • MochiKit.Base.isArrayLike no longer returns true for DOM text nodes
  • Added readonly-readOnly to the list of DOM renames for Internet Explorer
  • New MochiKit.Signal event method: confirmUnload (sets returnValue for onbeforeunload)
  • Fix interpreter help() function for Firefox and IE
  • API version compatibility notes added
  • New MochiKit.Base functions methodcaller and compose
  • Support IE-based native console logging (Debugger, Atlas)
  • Refactored style functions from MochiKit.DOM to MochiKit.Style
  • MochiKit.Async.DeferredList is now a proper Deferred
  • MochiKit.DOM.formContents now supports SELECT multiple tags
  • Re-use StopIteration Error if the browser already has it
  • Workaround IE type="" bug for INPUT elements
  • Allow LoggingPane to work in IE with hyphen-containing URLs
  • Replace percents for Safari native logging to avoid crashing
  • New MochiKit.DOM.coerceToDOM .dom(node) / .__dom__(node) protocol
  • MochiKit.DOM's MochiKit.Iter dependency is now optional
  • Added expand all link to the documentation index
  • Added MochiKit.DOM.isChildNode function.
  • Added synthesizing for onmouseenter/onmouseleave
  • Added animation functions and classes to MochiKit.Visual.
  • Added MochiKit.Style.getElementDimensions support for calculating the actual content size (without padding and borders).
  • Added MochiKit.DOM.insertSiblingNodesBefore, getFirstElementByTagAndClassName, getFirstParentByTagAndClassName, makeClipping, makePositioned, undoClipping, undoPositioned and removeEmptyTextNodes functions.
  • Added MochiKit.Base.bindLate, camelize, flattenArray, mean, median and noop functions.
  • New MochiKit.DragAndDrop module for drag and drop handling.
  • New MochiKit.Sortable module for lists sortable with drag and drop.
  • Changed MochiKit.Signal.connect to use late function binding also for non-DOM signals (#307).
  • Fixed MochiKit.Color.isColor when symbols not exported (#296).
  • Added support for inclusion in SVG files (#290).
  • Fixed rounding errors in MochiKit.Format.twoDigitFloat (#275).
  • Fixed MochiKit.Logging to convert log levels to strings (#273).
  • Fixed MochiKit.Iter.forEach and iextend for array-like objects with and iter function (#268).

2006-04-29 v1.3.1 (bug fix release)

  • Fix sendXMLHttpRequest sendContent regression
  • Internet Explorer fix in MochiKit.Logging (printfire exception)
  • Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async

2006-04-26 v1.3 "warp zone"

  • IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export)
  • IMPORTANT: Renamed MochiKit.Base.find to findValue (for export)
  • New MochiKit.Base.method as a convenience form of bind that takes the object before the method
  • New MochiKit.Base.flattenArguments for flattening a list of arguments to a single Array
  • Refactored MochiRegExp example to use MochiKit.Signal
  • New key_events example demonstrating use of MochiKit.Signal's key handling capabilities.
  • MochiKit.DOM.createDOM API change for convenience: if attrs is a string, null is used and the string will be considered the first node. This allows for the more natural P("foo") rather than P(null, "foo").
  • MochiKit Interpreter example refactored to use MochiKit.Signal and now provides multi-line input and a help() function to get MochiKit function signature from the documentation.
  • Native Console Logging for the default MochiKit.Logging logger
  • New MochiKit.Async.DeferredList, gatherResults, maybeDeferred
  • New MochiKit.Signal example: draggable
  • Added sanity checking to Deferred to ensure that errors happen when chaining is used incorrectly
  • Opera sendXMLHttpRequest fix (sends empty string instead of null by default)
  • Fix a bug in MochiKit.Color that incorrectly generated hex colors for component values smaller than 16/255.
  • Fix a bug in MochiKit.Logging that prevented logs from being capped at a maximum size
  • MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof Error, so that the errback chain is used instead of the callback chain.
  • MochiKit.DOM.appendChildNodes and associated functions now append iterables in the correct order.
  • New MochiKit-based SimpleTest test runner as a replacement for Test.Simple
  • MochiKit.Base.isNull no longer matches undefined
  • example doctypes changed to HTML4
  • isDateLike no longer throws error on null
  • New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt
  • updated elementDimensions to calculate width from offsetWidth instead of clientWidth
  • formContents now works with FORM tags that have a name attribute
  • Documentation now uses MochiKit to generate a function index

2006-01-26 v1.2 "the ocho"

  • Fixed MochiKit.Color.Color.lighterColorWithLevel
  • Added new MochiKit.Base.findIdentical function to find the index of an element in an Array-like object. Uses === for identity comparison.
  • Added new MochiKit.Base.find function to find the index of an element in an Array-like object. Uses compare for rich comparison.
  • MochiKit.Base.bind will accept a string for func, which will be immediately looked up as self[func].
  • MochiKit.DOM.formContents no longer skips empty form elements for Zope compatibility
  • MochiKit.Iter.forEach will now catch StopIteration to break
  • New MochiKit.DOM.elementDimensions(element) for determining the width and height of an element in the document
  • MochiKit.DOM's initialization is now compatible with HTMLUnit + JWebUnit + Rhino
  • MochiKit.LoggingPane will now re-use a _MochiKit_LoggingPane DIV element currently in the document instead of always creating one.
  • MochiKit.Base now has operator.mul
  • MochiKit.DOM.formContents correctly handles unchecked checkboxes that have a custom value attribute
  • Added new MochiKit.Color constructors fromComputedStyle and fromText
  • MochiKit.DOM.setNodeAttribute should work now
  • MochiKit.DOM now has a workaround for an IE bug when setting the style property to a string
  • MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the name and for properties
  • MochiKit.DOM.scrapeText now walks the DOM tree in-order
  • MochiKit.LoggingPane now sanitizes the window name to work around IE bug
  • MochiKit.DOM now translates usemap to useMap to work around IE bug
  • MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks
  • Added new MochiKit.DOM documentation on element visibility
  • New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}]) for determining the position of an element in the document
  • Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG

2005-11-14 v1.1

  • Fixed a bug in numberFormatter with large numbers
  • Massively overhauled documentation
  • Fast-path for primitives in MochiKit.Base.compare
  • New groupby and groupby_as_array in MochiKit.Iter
  • Added iterator factory adapter for objects that implement iterateNext()
  • Fixed isoTimestamp to handle timestamps with time zone correctly
  • Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP, LEGEND, FIELDSET
  • New MochiKit.DOM formContents and enhancement to queryString to support it
  • Updated view_source example to use dp.SyntaxHighlighter 1.3.0
  • MochiKit.LoggingPane now uses named windows based on the URL so that a given URL will get the same LoggingPane window after a reload (at the same position, etc.)
  • MochiKit.DOM now has currentWindow() and currentDocument() context variables that are set with withWindow() and withDocument(). These context variables affect all MochiKit.DOM functionality (getElement, createDOM, etc.)
  • MochiKit.Base.items will now catch and ignore exceptions for properties that are enumerable but not accessible (e.g. permission denied)
  • MochiKit.Async.Deferred's addCallback/addErrback/addBoth now accept additional arguments that are used to create a partially applied function. This differs from Twisted in that the callback/errback result becomes the last argument, not the first when this feature is used.
  • MochiKit.Async's doSimpleXMLHttpRequest will now accept additional arguments which are used to create a GET query string
  • Did some refactoring to reduce the footprint of MochiKit by a few kilobytes
  • escapeHTML to longer escapes ' (apos) and now uses String.replace instead of iterating over every char.
  • Added DeferredLock to Async
  • Renamed getElementsComputedStyle to computedStyle and moved it from MochiKit.Visual to MochiKit.DOM
  • Moved all color support out of MochiKit.Visual and into MochiKit.Color
  • Fixed range() to accept a negative step
  • New alias to MochiKit.swapDOM called removeElement
  • New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets an attribute on a node without raising, roughly equivalent to: updateNodeAttributes(node, {attr: value})
  • New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of a node's attribute or returns null without raising
  • Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack directly (addLoadEvent did not leak, since it clears the handler)

2005-10-24 v1.0

  • New interpreter example that shows usage of MochiKit.DOM to make an interactive JavaScript interpreter
  • New MochiKit.LoggingPane for use with the MochiKit.Logging debuggingBookmarklet, with logging_pane example to show its usage
  • New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async in order to provide a live regular expression matching tool
  • Added advanced number formatting capabilities to MochiKit.Format: numberFormatter(pattern, placeholder="", locale="default") and formatLocale(locale="default")
  • Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate.
  • Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE
  • Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision) to MochiKit.Format
  • MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically isoTimestamp(isoString) will convert them to Date objects, and toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC
  • Fixed missing errback for sendXMLHttpRequest when the server does not respond
  • Fixed infinite recusion bug when using roundClass("DIV", ...)
  • Fixed a bug in MochiKit.Async wait (and callLater) that prevented them from being cancelled properly
  • Workaround in MochiKit.Base bind (and partial) for functions that don't have an apply method, such as alert
  • Reliably return null from the string parsing/manipulation functions if the input can't be coerced to a string (s + "") or the input makes no sense; e.g. isoTimestamp(null) and isoTimestamp("") return null

2005-10-08 v0.90

  • Fixed ISO compliance with toISODate
  • Added missing operator.sub
  • Placated Mozilla's strict warnings a bit
  • Added JSON serialization and unserialization support to MochiKit.Base: serializeJSON, evalJSON, registerJSON. This is very similar to the repr API.
  • Fixed a bug in the script loader that failed in some scenarios when a script tag did not have a "src" attribute (thanks Ian!)
  • Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA, P, FORM
  • Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode and parseQueryString, when available.

2005-08-12 v0.80

  • Source highlighting in all examples, moved to a view-source example
  • Added some experimental syntax highlighting for the Rounded Corners example, via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib
  • Use an indirect binding for the logger conveniences, so that the global logger could be replaced by setting MochiKit.Logger.logger to something else (though an observer is probably a better choice).
  • Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent, which will be looked up with getElement
  • Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of node.parentNode)
  • Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success
  • Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues
  • Possible workaround for Safari issue with swapDOM, where it would get confused because two elements were in the DOM at the same time with the same id
  • Added missing THEAD convenience function to MochiKit.DOM
  • Added lstrip, rstrip, strip to MochiKit.Format
  • Added updateNodeAttributes, appendChildNodes, replaceChildNodes to MochiKit.DOM
  • MochiKit.Iter.iextend now has a fast-path for array-like objects
  • Added HSV color space support to MochiKit.Visual
  • Fixed a bug in the sortable_tables example, it now converts types correctly
  • Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global scope

2005-08-04 v0.70

  • New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and a little TAL-ish DOM templating attribute language.
  • sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer ignore requests with status == 0, which seems to happen for cached or local requests
  • Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh.
  • Changed scrapeText API to return a string by default. This is API-breaking! It was dumb to have the default return value be the form you almost never want. Sorry.
  • Added special form to swapDOM(dest, src). If src is null, dest is removed (where previously you'd likely get a DOM exception).
  • Added three new functions to MochiKit.Base for dealing with URL query strings: urlEncode, queryString, parseQueryString
  • MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name starts with "on" (e.g. "onclick"). If v is a string, it will set it to new Function(v).
  • Another workaround for Internet "worst browser ever" Explorer's setAttribute usage in MochiKit.DOM.createDOM (checked -> defaultChecked).
  • Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM
  • Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller now!

2005-07-29 v0.60

  • Beefed up the MochiKit.DOM test suite
  • Fixed return value for MochiKit.DOM.swapElementClass, could return false unexpectedly before
  • Added an optional "parent" argument to MochiKit.DOM.getElementsByTagAndClassName
  • Added a "packed" version in packed/lib/MochiKit/MochiKit.js
  • Changed build script to rewrite the URLs in tests to account for the JSAN-required reorganization
  • MochiKit.Compat to potentially work around IE 5.5 issues (5.0 still not supported). Test.Simple doesn't seem to work there, though.
  • Several minor documentation corrections

2005-07-27 v0.50

  • Initial Release

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Base.html0000660000175000017500000026153111113647640017270 0ustar scottscott MochiKit.Base - functional programming and useful comparisons MochiKit Back to docs index

Name

MochiKit.Base - functional programming and useful comparisons

Synopsis

myObjectRepr = function () {
    // gives a nice, stable string representation for objects,
    // ignoring any methods
    var keyValuePairs = [];
    for (var k in this) {
        var v = this[k];
        if (typeof(v) != 'function') {
            keyValuePairs.push([k, v]);
        }
    };
    keyValuePairs.sort(compare);
    return "{" + map(
        function (pair) {
            return map(repr, pair).join(":");
        },
        keyValuePairs
    ).join(", ") + "}";
};

// repr() will look for objects that have a repr method
myObjectArray = [
    {"a": 3, "b": 2, "repr": myObjectRepr},
    {"a": 1, "b": 2, "repr": myObjectRepr}
];

// sort it by the "a" property, check to see if it matches
myObjectArray.sort(keyComparator("a"));
expectedRepr = '[{"a": 1, "b": 2}, {"a": 3, "b": 2}]';
assert( repr(myObjectArray) == expectedRepr );

// get just the "a" values out into an array
sortedAValues = map(itemgetter("a"), myObjectArray);
assert( compare(sortedAValues, [1, 3]) == 0 );

// serialize an array as JSON, unserialize it, expect something equivalent
myArray = [1, 2, "3", null, undefined];
assert( objEqual(evalJSON(serializeJSON(myArray)), myArray) );

Description

MochiKit.Base is the foundation for the MochiKit suite. It provides:

Python users will feel at home with MochiKit.Base, as the facilities are quite similar to those available as part of Python and the Python standard library.

Dependencies

None.

Overview

Comparison

The comparators (operators for comparison) in JavaScript are deeply broken, and it is not possible to teach them new tricks.

MochiKit exposes an extensible comparison facility as a simple compare(a, b) function, which should be used in lieu of JavaScript's operators whenever comparing objects other than numbers or strings (though you can certainly use compare for those, too!).

The compare function has the same signature and return value as a sort function for Array.prototype.sort, and is often used in that context.

Defining new comparators for the compare function to use is done by adding an entry to its AdapterRegistry with the registerComparator function.

Programmer Representation

JavaScript's default representation mechanism, toString, is notorious for having terrible default behavior. It's also very unwise to change that default, as other JavaScript code you may be using may depend on it.

It's also useful to separate the concept of a "string representation" and a "string representation for programmers", much like Python does with its str and repr protocols.

repr provides this programmer representation for JavaScript, in a way that doesn't require object prototype hacking: using an AdapterRegistry.

Objects that implement the repr protocol can either implement a .repr() or .__repr__() method, or they can simply have an adapter setup to generate programmer representations. By default, the registry provides nice representations for null, undefined, Array, and objects or functions with a NAME attribute that use the default toString. For objects that repr doesn't already understand, it simply defaults to toString, so it will integrate seamlessly with code that implements the idiomatic JavaScript toString method!

To define a programmer representation for your own objects, simply add a .repr() or .__repr__() method that returns a string. For objects that you didn't create (e.g., from a script you didn't write, or a built-in object), it is instead recommended that you create an adapter with registerRepr.

JSON Serialization

JSON [1], JavaScript Object Notation, is a widely used serialization format in the context of web development. It's extremely simple, lightweight, and fast. In its essence, JSON is a restricted subset of JavaScript syntax suitable for sending over the wire that can be unserialized with a simple eval. It's often used as an alternative to XML in "AJAX" contexts because it is compact, fast, and much simpler to use for most purposes.

To create a JSON serialization of any object, simply call serializeJSON() with that object. To unserialize a JSON string, simply call evalJSON() with the serialization.

In order of precedence, serializeJSON coerces the given argument into a JSON serialization:

  1. Primitive types are returned as their JSON representation: string, number, boolean, null.
  2. If the object has a __json__ or json method, then it is called with no arguments. If the result of this method is not the object itself, then the new object goes through rule processing again (e.g. it may return a string, which is then serialized in JSON format).
  3. If the object is Array-like (has a length property that is a number, and is not a function), then it is serialized as a JSON array. Each element will be processed according to these rules in order. Elements that can not be serialized (e.g. functions) will be replaced with undefined.
  4. The jsonRegistry AdapterRegistry is consulted for an adapter for this object. JSON adapters take one argument (the object), and are expected to behave like a __json__ or json method (return another object to be serialized, or itself).
  5. If the object is undefined, a TypeError is thrown. If you wish to serialize undefined as null or some other value, you should create an adapter to do so.
  6. If no adapter is available, the object is enumerated and serialized as a JSON object (name:value pairs). All names are expected to be strings. Each value is serialized according to these rules, and if it can not be serialized (e.g. methods), then that name:value pair will be skipped.

Adapter Registries

MochiKit makes extensive use of adapter registries, which enable you to implement object-specific behaviors for objects that you do not necessarily want to modify, such as built-in objects. This is especially useful because JavaScript does not provide a method for hiding user-defined properties from for propName in obj enumeration.

AdapterRegistry is simply an encapsulation for an ordered list of "check" and "wrap" function pairs. Each AdapterRegistry instance should perform one function, but may have multiple ways to achieve that function based upon the arguments. One way to think of it is as a poor man's generic function, or multiple dispatch (on arbitrary functions, not just type!).

Check functions take one or more arguments, and return true if the argument list is suitable for the wrap function. Check functions should perform "cheap" checks of an object's type or contents, before the "expensive" wrap function is called.

Wrap functions take the same arguments as check functions and do some operation, such as creating a programmer representation or comparing both arguments.

Convenience Functions

Much of MochiKit.Base is there to simply remove the grunt work of doing generic JavaScript programming.

Need to take every property from one object and set them on another? No problem, just call update(dest, src)! What if you just wanted to update keys that weren't already set? Look no further than setdefault(dest, src[, ...]).

Want to return a mutable object, but don't want to suffer the consequences if the user mutates it? Just clone(it) and you'll get a copy-on-write clone. Cheaper than a copy!

Need to extend an Array with another array? Or even an Array-like object such as a NodeList or the special arguments object? Even if you need to skip the first few elements of the source Array-like object, it's no problem with extend(dstArray, srcArrayLike[, skip])!

Wouldn't it be convenient to have all of the JavaScript operators were available as functions somewhere? That's what the operators table is for, and it even comes with additional operators based on the compare function.

Need to walk some tree of objects and manipulate or find something in it? A DOM element tree perhaps? Use nodeWalk(node, visitor)!

There's plenty more, so check out the API Reference below.

Functional Programming

Functional programming constructs such as map and filter can save you a lot of time, because JavaScript iteration is error-prone and arduous. Writing less code is the best way to prevent bugs, and functional programming can help you do that.

MochiKit.Base ships with a few simple Array-based functional programming constructs, namely map and filter, and their "extended" brethren, xmap and xfilter.

map(func, arrayLike[, ...]) takes a function and an Array-like object, and creates a new Array. The new Array is the result of func(element) for every element of arrayLike, much like the Array.prototype.map extension in Mozilla. However, MochiKit.Base takes that a step further and gives you the full blown Python version of map, which will take several Array-like objects, and calls the function with one argument per given Array-like, e.g.:

var arrayOne = [1, 2, 3, 4, 5];
var arrayTwo = [1, 5, 2, 4, 3];
var arrayThree = [5, 2, 1, 3, 4];
var biggestElements = map(objMax, arrayOne, arrayTwo, arrayThree);
assert( objEqual(biggestElements, [5, 5, 3, 4, 5]) );

filter(func, arrayLike[, self]) takes a function and an Array-like object, and returns a new Array. This is basically identical to the Array.prototype.filter extension in Mozilla. self, if given, will be used as this in the context of func when called.

xmap and xfilter are just special forms of map and filter that accept a function as the first argument, and use the extra arguments as the Array-like. Not terribly interesting, but a definite time-saver in some cases.

If you appreciate the functional programming facilities here, you should definitely check out MochiKit.Iter, which provides full blown iterators, MochiKit.Iter.range, MochiKit.Iter.reduce, and a near-complete port of Python's itertools [2] module, with some extra stuff thrown in for good measure!

Bound and Partial Functions

JavaScript's method-calling special form and lack of bound functions (functions that know what this should be) are one of the first stumbling blocks that programmers new to JavaScript face. The bind(func, self) method fixes that right up by returning a new function that calls func with the right this.

In order to take real advantage of all this fancy functional programming stuff, you're probably going to want partial application. This allows you to create a new function from an existing function that remembers some of the arguments. For example, if you wanted to compare a given object to a slew of other objects, you could do something like this:

compareWithOne = partial(compare, 1);
results = map(compareWithOne, [0, 1, 2, 3]);
assert( objEqual(results, [-1, 0, 1, 1]) );

One of the better uses of partial functions is in MochiKit.DOM, which is certainly a must-see for those of you creating lots of DOM elements with JavaScript!

API Reference

Errors

NotFound:

A singleton error raised when no suitable adapter is found

Availability:
Available in MochiKit 1.3.1+

Constructors

AdapterRegistry:

A registry to facilitate adaptation.

All check/wrap function pairs in a given registry should take the same number of arguments.

Availability:
Available in MochiKit 1.3.1+

AdapterRegistry.prototype.register(name, check, wrap[, override]):

name:
a unique identifier used to identify this adapter so that it may be unregistered.
check:
function that should return true if the given arguments are appropriate for the wrap function.
wrap:
function that takes the same parameters as check and does the adaptation. Every wrap/check function pair in the registry should have the same number of arguments.
override:
if true, the check function will be given highest priority. Otherwise, the lowest.
Availability:
Available in MochiKit 1.3.1+

AdapterRegistry.prototype.match(obj[, ...]):

Find an adapter for the given arguments by calling every check function until one returns true.

If no suitable adapter is found, throws NotFound.

Availability:
Available in MochiKit 1.3.1+

AdapterRegistry.prototype.unregister(name):

Remove a named adapter from the registry

Availability:
Available in MochiKit 1.3.1+

NamedError:

Convenience constructor for creating new errors (e.g. NotFound)

Availability:
Available in MochiKit 1.3.1+

Functions

arrayEqual(self, arr):

Compare the arrays self and arr for equality using compare on each element. Uses a fast-path for length differences.

Availability:
Available in MochiKit 1.3.1+

average(lst[, ...]):

This function is an alias of mean().

Availability:
Available in MochiKit 1.3.1+

bind(func, self[, arg, ...]):

Return a copy of func bound to self. This means whenever and however the returned function is called, this will always reference the given self. func may be either a function object, or a string. If it is a string, then self[func] will be used, making these two statements equivalent:

bind("method", self);
bind(self.method, self);

Calling bind(func, self) on an already bound function will return a new function that is bound to the new self! If self is undefined, then the previous self is used. If self is null, then the this object is used (which may or may not be the global object). To force binding to the global object, you should pass it explicitly.

Additional arguments, if given, will be partially applied to the function. These three expressions are equivalent and return equally efficient functions (bind and partial share the same code path):

Availability:
Available in MochiKit 1.3.1+

bindLate(func, self[, arg, ...]):

Alternate version of bind that uses late lookup of the func parameter in self. I.e, the self[func] function lookup will occur on each call to the returned function, not when bindLate is called. Note that this difference is only applicable when func is a string, otherwise bindLate and bind are identical.

Availability:
Available in MochiKit 1.4+

bindMethods(self):

Replace all functions meth on self with bind(meth, self). This emulates Python's bound instance methods, where there is no need to worry about preserving this when the method is used as a callback.

Availability:
Available in MochiKit 1.3.1+

camelize(str):

Converts hyphenated strings to camelCase:

assert( camelize("border-left") == "borderLeft" );
Availability:
Available in MochiKit 1.4+

clone(obj):

Return a new object using obj as its prototype. Use this if you want to return a mutable object (e.g. instance state), but don't want the user to mutate it. If they do, it won't have any effect on the original obj.

Note that this is a shallow clone, so mutable properties will have to be cloned separately if you want to "protect" them.

Availability:
Available in MochiKit 1.3.1+

compare(a, b):

Compare two objects in a sensible manner. Currently this is:

  1. undefined and null compare equal to each other
  2. undefined and null are less than anything else
  3. If JavaScript says a == b, then we trust it
  4. comparators registered with registerComparator are used to find a good comparator. Built-in comparators are currently available for Array-like and Date-like objects.
  5. Otherwise hope that the built-in comparison operators do something useful, which should work for numbers and strings.
  6. If neither a < b or a > b, then throw a TypeError

Returns what one would expect from a comparison function:

Value Condition
0 a == b
1 a > b
-1 a < b
Availability:
Available in MochiKit 1.3.1+

compose(f1, f2, ..., fN):

Return a new function as the combination of the given function arguments, equivalent to f1(f2(arguments)).

Availability:
Available in MochiKit 1.4+

concat(lst[, ...]):

Concatenates all given Array-like arguments and returns a new Array:

var lst = concat(["1","3","5"], ["2","4","6"]);
assert( lst.toString() == "1,3,5,2,4,6" );
Availability:
Available in MochiKit 1.3.1+

counter(n=1):

Returns a function that will return a number one greater than the previous returned value, starting at n. For example:

nextId = counter()
assert( nextId() == 1 )
assert( nextId() == 2 )

For an iterator with this behavior, see MochiKit.Iter.count.

Availability:
Available in MochiKit 1.3.1+

extend(self, obj, skip=0):

Mutate the array self by extending it with an Array-like obj, starting from index skip. If null is given as the initial array, a new one will be created.

This mutates and returns self, be warned.

Availability:
Available in MochiKit 1.3.1+

evalJSON(aJSONString):

Unserialize a JSON [1] represenation of an object.

Note that this uses the eval function of the interpreter, and therefore trusts the contents of aJSONString to be safe. This is acceptable when the JSON and JavaScript application originate from the same server, but in other scenarios it may not be the appropriate security model. Currently, a validating JSON parser is beyond the scope of MochiKit, but there is one available from json.org [1].

Availability:
Available in MochiKit 1.3.1+

filter(fn, lst):

Returns a new Array composed of all elements from lst where fn(lst[i]) returns a true value.

If fn is null, operator.truth will be used.

Availability:
Available in MochiKit 1.3.1+

findValue(lst, value, start=0, end=lst.length):

Finds the index of value in the Array-like object lst using compare. The search starts at the index start, and ends at the index end - 1. If value is not found in lst, it will return -1.

For example:

assert( findValue([1, 2, 3, 2, 1], 2) == 1 )
assert( findValue([1, 2, 3, 2, 1], 2, 2) == 3 )
Availability:
Available in MochiKit 1.3.1+

findIdentical(lst, value, start=0, end=lst.length):

Finds the index of value in the Array-like object lst using the === operator. The search starts at the index start, and ends at the index end - 1. If value is not found in lst, it will return -1.

You should use this function instead of findValue if lst may be comprised of objects for which no comparator is defined and all you care about is finding an identical object (e.g. the same instance), or if lst is comprised of just numbers or strings and performance is important.

For example:

assert( findIdentical([1, 2, 3, 2, 1], 2) == 1 )
assert( findIdentical([1, 2, 3, 2, 1], 2, 2) == 3 )
Availability:
Available in MochiKit 1.3.1+

flattenArguments(arg[, ...]):

Given a bunch of arguments, return a single Array containing all of those arguments. Any Array-like argument will be extended in-place, e.g.:

compare(flattenArguments(1, [2, 3, [4, 5]]), [1, 2, 3, 4, 5]) == 0
Availability:
Available in MochiKit 1.3.1+

flattenArray(lst):

Return a new Array consisting of every item in lst with Array items expanded in-place recursively. This differs from flattenArguments in that it only takes one argument and it only flattens items that are instanceof Array.

compare(flattenArray([1, [2, 3, [4, 5]]]), [1, 2, 3, 4, 5]) == 0
Availability:
Available in MochiKit 1.4+

forwardCall(name):

Returns a function that forwards a method call to this.name(...)

Availability:
Available in MochiKit 1.3.1+

isArrayLike(obj[, ...]):

Returns true if all given arguments are Array-like (have a .length property and typeof(obj) == 'object')

Availability:
Available in MochiKit 1.3.1+

isDateLike(obj[, ...]):

Returns true if all given arguments are Date-like (have a .getTime() method)

Availability:
Available in MochiKit 1.3.1+

isEmpty(obj[, ...]):

Returns true if all the given Array-like or string arguments are empty (obj.length == 0)

Availability:
Available in MochiKit 1.3.1+

isNotEmpty(obj[, ...]):

Returns true if all the given Array-like or string arguments are not empty (obj.length > 0)

Availability:
Available in MochiKit 1.3.1+

isNull(obj[, ...]):

Returns true if all arguments are null.

Availability:
Available in MochiKit 1.3.1+

isUndefinedOrNull(obj[, ...]):

Returns true if all arguments are undefined or null

Availability:
Available in MochiKit 1.3.1+

itemgetter(name):

Returns a function(obj) that returns obj[name]

Availability:
Available in MochiKit 1.3.1+

items(obj):

Return an Array of [propertyName, propertyValue] pairs for the given obj (in the order determined by for propName in obj).

Availability:
Available in MochiKit 1.3.1+

keyComparator(key[, ...]):

A comparator factory that compares a[key] with b[key]. e.g.:

var lst = ["a", "bbb", "cc"];
lst.sort(keyComparator("length"));
assert( lst.toString() == "a,cc,bbb" );
Availability:
Available in MochiKit 1.3.1+

keys(obj):

Return an Array of the property names of an object (in the order determined by for propName in obj).

Availability:
Available in MochiKit 1.3.1+

listMax(lst):

Return the largest element of an Array-like object, as determined by compare. This is a special form of listMinMax, specifically partial(listMinMax, 1).

Availability:
Available in MochiKit 1.3.1+

listMin(lst):

Return the smallest element of an Array-like object, as determined by compare. This is a special form of listMinMax, specifically partial(listMinMax, -1).

Availability:
Available in MochiKit 1.3.1+

listMinMax(which, lst):

If which == -1 then it will return the smallest element of the Array-like lst. This is also available as listMin(lst).

If which == 1 then it will return the largest element of the Array-like lst. This is also available as listMax(list).

Availability:
Available in MochiKit 1.3.1+

map(fn, lst[, ...]):

Return a new array composed of the results of fn(x) for every x in lst.

If fn is null, and only one sequence argument is given the identity function is used.

map(null, lst) -> lst.slice();

If fn is not null and more than one sequence argument is given, then one element from each sequence is used to build the argument list for fn.

map(fn, p, q, ...)
-> [fn(p[0], q[0], ..), fn(p[1], q[1], ...), ...]

If fn is null, and more than one sequence is given as arguments, then the Array function is used.

map(null, p, q, ...)
-> MochiKit.Iter.zip(p, q, ...) -> [[p0, q0, ...], [p1, q1, ...], ...];

Since this is a common idiom, zip(p, q, ...) is actually a shortcut for this.

Availability:
Available in MochiKit 1.3.1+

mean(lst[, ...]):

Returns the arithmetic mean (average) of the argument list, or an array. This function applies flattenArguments() to the argument list.

Availability:
Available in MochiKit 1.4+

median(lst[, ...]):

Returns the median of the argument list, or an array. This function applies flattenArguments() to the argument list.

Availability:
Available in MochiKit 1.4+

merge(obj[, ...]):

Create a new instance of Object that contains every property from all given objects. If a property is defined on more than one of the objects, the last property is used.

This is a special form of update(self, obj[, ...]), specifically, it is defined as partial(update, null).

Availability:
Available in MochiKit 1.3.1+

method(self, func, ...):

Alternate form of bind that takes the object before the function. These two calls are equivalent:

bind("method", myobject)
method(myobject, "method")
Availability:
Available in MochiKit 1.3.1+

methodcaller(name[, args...]):

Return a new function that calls a method on its argument, for example:

lst = map(methodcaller("toLowerCase"), ["THIS", "is", "LoWeRCaSe"]);
assert( lst.join(" ") == "this is lowercase" );
Availability:
Available in MochiKit 1.4+

nameFunctions(namespace):

Given a namespace (object or function) with a NAME property, find all methods in it and give them nice NAME properties too (for use with repr). e.g.:

namespace = {
    NAME: "Awesome",
    Dude: function () {}
}
nameFunctions(namespace);
assert( namespace.Dude.NAME == 'Awesome.Dude' );
Availability:
Available in MochiKit 1.3.1+

noop():

A function that performs no operation. Use this where you would otherwise use (function () {}) in order to avoid Internet Explorer cyclic garbage leakage.

Availability:
Available in MochiKit 1.4

objEqual(a, b):

Return true if compare(a, b) == 0

Availability:
Available in MochiKit 1.3.1+

nodeWalk(node, visitor):

Non-recursive generic node walking function (e.g. for a DOM).

The walk order for nodeWalk is breadth first, meaning that all siblings will be visited before any children.

node:
The initial node to be searched.
visitor:
The visitor function, will be called as visitor(node), and should return an Array-like of nodes to be searched next (e.g. node.childNodes). Leaf nodes may return null or undefined.
Availability:
Available in MochiKit 1.3.1+

objMax(obj[, ...]):

Return the maximum object according to compare out of the given arguments. This is similar to listMax, except is uses the arguments instead of a given Array-like.

Availability:
Available in MochiKit 1.3.1+

objMin(obj[, ...]):

Return the minimum object according to compare out of the given arguments. This is similar to listMin, except it uses the arguments instead of a given Array-like.

Availability:
Available in MochiKit 1.3.1+

operator:

A table of JavaScript's operators for usage with map, filter, etc.

Unary Logic Operators:

Operator Implementation Description
truth(a) !!a Logical truth
lognot(a) !a Logical not
identity(a) a Logical identity

Unary Math Operators:

Operator Implementation Description
not(a) ~a Bitwise not
neg(a) -a Negation

Binary Operators:

Operator Implementation Description
add(a, b) a + b Addition
sub(a, b) a - b Subtraction
div(a, b) a / b Division
mod(a, b) a % b Modulus
mul(a, b) a * b Multiplication
and(a, b) a & b Bitwise and
or(a, b) a | b Bitwise or
xor(a, b) a ^ b Bitwise exclusive or
lshift(a, b) a << b Bitwise left shift
rshift(a, b) a >> b Bitwise signed right shift
zrshift(a, b) a >>> b Bitwise unsigned right shift

Built-in Comparators:

Operator Implementation Description
eq(a, b) a == b Equals
ne(a, b) a != b Not equals
gt(a, b) a > b Greater than
ge(a, b) a >= b Greater than or equal to
lt(a, b) a < b Less than
le(a, b) a <= b Less than or equal to

Strict Built-in Comparators:

Operator Implementation Description
seq(a, b) a === b Strict equals
sne(a, b) a !== b Strict not equals

Extended Comparators (uses compare):

Operator Implementation Description
ceq(a, b) compare(a, b) == 0 Equals
cne(a, b) compare(a, b) != 0 Not equals
cgt(a, b) compare(a, b) == 1 Greater than
cge(a, b) compare(a, b) != -1 Greater than or equal to
clt(a, b) compare(a, b) == -1 Less than
cle(a, b) compare(a, b) != 1 Less than or equal to

Binary Logical Operators:

Operator Implementation Description
logand(a, b) a && b Logical and
logor(a, b) a || b Logical or
contains(a, b) b in a Has property (note order)
Availability:
Available in MochiKit 1.3.1+

parseQueryString(encodedString[, useArrays=false]):

Parse a name=value pair URL query string into an object with a property for each pair. e.g.:

var args = parseQueryString("foo=value%20one&bar=two");
assert( args.foo == "value one" && args.bar == "two" );

If you expect that the query string will reuse the same name, then give true as a second argument, which will use arrays to store the values. e.g.:

var args = parseQueryString("foo=one&foo=two", true);
assert( args.foo[0] == "one" && args.foo[1] == "two" );
Availability:
Available in MochiKit 1.3.1+

partial(func, arg[, ...]):

Return a partially applied function, e.g.:

addNumbers = function (a, b) {
    return a + b;
}

addOne = partial(addNumbers, 1);

assert(addOne(2) == 3);

partial is a special form of bind that does not alter the bound self (if any). It is equivalent to calling:

bind(func, undefined, arg[, ...]);

See the documentation for bind for more details about this facility.

This could be used to implement, but is NOT currying.

Availability:
Available in MochiKit 1.3.1+

queryString(names, values):

Creates a URL query string from a pair of Array-like objects representing names and values. Each name=value pair will be URL encoded by urlEncode. name=value pairs with a value of undefined or null will be skipped. e.g.:

var keys = ["foo", "bar"];
var values = ["value one", "two"];
assert( queryString(keys, values) == "foo=value%20one&bar=two" );
Alternate form 1:
queryString(domElement)

If MochiKit.DOM is loaded, one argument is given, and that argument is either a string or has a nodeType property greater than zero, then names and values will be the result of MochiKit.DOM.formContents(domElement).

Alternate form 2:
queryString({name: value, ...})

Note that when using the alternate form, the order of the name=value pairs in the resultant query string is dependent on how the particular JavaScript implementation handles for (..in..) property enumeration.

When using the second alternate form, name=value pairs with typeof(value) == "function" are ignored. This is a workaround for the case where a poorly designed library has modified Object.prototype and inserted "convenience functions".

Values that are Array-like will be expanded as if they were multiply defined HTML elements. For example:

assert( queryString({a: [1,2]}) === "a=1&a=2" );
Alternate form 2 (MochiKit 1.4+):
queryString([names, values])

This form behaves identically to queryString(names, values), except it takes both arguments as a single Array. This mirrors the return value of MochiKit.DOM.formContents.

Availability:
Available in MochiKit 1.3.1+

registerComparator(name, check, comparator[, override]):

Register a comparator for use with compare.

name:
unique identifier describing the comparator.
check:
function(a, b) that returns true if a and b can be compared with comparator.
comparator:

function(a, b) that returns:

Value Condition
0 a == b
1 a > b
-1 a < b

comparator is guaranteed to only be called if check(a, b) returns a true value.

override:
if true, then this will be made the highest precedence comparator. Otherwise, the lowest.
Availability:
Available in MochiKit 1.3.1+

registerJSON(name, check, simplifier[, override]):

Register a simplifier function for use with serializeJSON.

name:
unique identifier describing the serialization.
check:
function(obj) that returns true if obj can can be simplified for serialization by simplifier.
simplifier:

function(obj) that returns a simpler object that can be further serialized by serializeJSON. For example, you could simplify Date-like objects to ISO 8601 timestamp strings with the following simplifier:

var simplifyDateAsISO = function (obj) {
    return toISOTimestamp(obj, true);
};
registerJSON("DateLike", isDateLike, simplifyDateAsISO);

simplifier is guaranteed to only be called if check(obj) returns a true value.

override:
if true, then this will be made the highest precedence serialization. Otherwise, the lowest.
Availability:
Available in MochiKit 1.3.1+

registerRepr(name, check, wrap[, override]):

Register a programmer representation function. repr functions should take one argument and return a string representation of it suitable for developers, primarily used when debugging.

If override is given, it is used as the highest priority repr, otherwise it will be used as the lowest.

Availability:
Available in MochiKit 1.3.1+

repr(obj):

Return a programmer representation for obj. See the Programmer Representation overview for more information about this function.

Availability:
Available in MochiKit 1.3.1+

reverseKeyComparator(key):

A comparator factory that compares a[key] with b[key] in reverse. e.g.:

var lst = ["a", "bbb", "cc"];
lst.sort(reverseKeyComparator("length"));
assert(lst.toString() == "bbb,cc,a");
Availability:
Available in MochiKit 1.3.1+

serializeJSON(anObject):

Serialize anObject in the JSON [1] format, see JSON Serialization for the coercion rules. For unserializable objects (functions that do not have an adapter, __json__ method, or json method), this will return undefined.

For those familiar with Python, JSON is similar in scope to pickle, but it can not handle recursive object graphs.

Availability:
Available in MochiKit 1.3.1+

setdefault(self, obj[, ...]):

Mutate self by adding all properties from other object(s) that it does not already have set.

If self is null, a new Object instance will be created and returned.

This mutates and returns self, be warned.

Availability:
Available in MochiKit 1.3.1+

typeMatcher(typ[, ...]):

Given a set of types (as string arguments), returns a function(obj[, ...]) that will return true if the types of the given arguments are all members of that set.

Availability:
Available in MochiKit 1.3.1+

update(self, obj[, ...]):

Mutate self by replacing its key:value pairs with those from other object(s). Key:value pairs from later objects will overwrite those from earlier objects.

If self is null, a new Object instance will be created and returned.

This mutates and returns self, be warned.

A version of this function that creates a new object is available as merge(a, b[, ...])

Availability:
Available in MochiKit 1.3.1+

updatetree(self, obj[, ...]):

Mutate self by replacing its key:value pairs with those from other object(s). If a given key has an object value in both self and obj, then this function will be called recursively, updating instead of replacing that object.

If self is null, a new Object instance will be created and returned.

This mutates and returns self, be warned.

Availability:
Available in MochiKit 1.3.1+

urlEncode(unencoded):

Converts unencoded into a URL-encoded string. In this implementation, spaces are converted to %20 instead of "+". e.g.:

assert( URLencode("1+2=2") == "1%2B2%3D2");
Availability:
Available in MochiKit 1.3.1+

values(obj):

Return an Array of the property values of an object (in the order determined by for propName in obj).

Availability:
Available in MochiKit 1.4+

xfilter(fn, obj[, ...]):

Returns a new Array composed of the arguments where fn(obj) returns a true value.

If fn is null, operator.truth will be used.

Availability:
Available in MochiKit 1.3.1+

xmap(fn, obj[, ...):

Return a new Array composed of fn(obj) for every obj given as an argument.

If fn is null, operator.identity is used.

Availability:
Available in MochiKit 1.3.1+

zip(p, q, ...):

Returns an array where the n-th element is an array of the n-th elements from each of the arrays p, q, ...

This is equivalent to calling map(fn, p, q, ...) with null as the first argument.

zip(p, q, ...)
-> map(null, p, q, ...) -> [[p0, q0, ...], [p1, q1, ...], ...];
Availability:
Available in MochiKit 1.3.1+

See Also

[1](1, 2, 3, 4, 5) JSON, JavaScript Object Notation: http://json.org/
[2]Python's itertools module: http://docs.python.org/lib/module-itertools.html

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Async.html0000660000175000017500000012526211113647640017473 0ustar scottscott MochiKit.Async - manage asynchronous tasks MochiKit Back to docs index

Name

MochiKit.Async - manage asynchronous tasks

Synopsis

var url = "/src/b/bo/bob/MochiKit.Async/META.json";
/*

    META.json looks something like this:

    {"name": "MochiKit", "version": "0.5"}

*/
var d = loadJSONDoc(url);
var gotMetadata = function (meta) {
    if (MochiKit.Async.VERSION == meta.version) {
        alert("You have the newest MochiKit.Async!");
    } else {
        alert("MochiKit.Async "
            + meta.version
            + " is available, upgrade!");
    }
};
var metadataFetchFailed = function (err) {
  alert("The metadata for MochiKit.Async could not be fetched :(");
};
d.addCallbacks(gotMetadata, metadataFetchFailed);

Description

MochiKit.Async provides facilities to manage asynchronous (as in AJAX [1]) tasks. The model for asynchronous computation used in this module is heavily inspired by Twisted [2].

Security Concerns

The current implementation of evalJSONRequest does no input validation. Invalid JSON can execute arbitrary JavaScript code in the client. This isn't normally a concern because of the same-origin policy in web browsers; the server is already sending arbitrary code to the client (your program!).

While this isn't directly relevant to MochiKit, server-side code that produces JSON should consider potential cross-site request forgery. Currently known exploits require a JSON array to be the outer-most object, and the data to be leaked must be known keys in objects contained by that array:

[{"some_known_key": "this can be leaked"}, "but not this"]

This exploit does not apply to the most common usage of JSON, sending an object:

{"some_known_key": "this can't be leaked"}

There are several ways to avoid this, here are a few:

  • Use some non-standard addition to JSON that adds constructs to prevent script tag parsing, such as wrapping the data in a comment or an infinite loop. MochiKit supports comment-wrapped JSON, but it's up to the server to send it that way.
  • Require some kind of authentication token in the URL.
  • Allow only POST requests to access sensitive JSON.
  • Only send JSON objects, not arrays. JSON objects aren't valid JavaScript syntax on their own without parentheses.

Overview

Deferred

The Deferred constructor encapsulates a single value that is not available yet. The most important example of this in the context of a web browser would be an XMLHttpRequest to a server. The importance of the Deferred is that it allows a consistent API to be exposed for all asynchronous computations that occur exactly once.

The producer of the Deferred is responsible for doing all of the complicated work behind the scenes. This often means waiting for a timer to fire, or waiting for an event (e.g. onreadystatechange of XMLHttpRequest). It could also be coordinating several events (e.g. XMLHttpRequest with a timeout, or several Deferreds (e.g. fetching a set of XML documents that should be processed at the same time).

Since these sorts of tasks do not respond immediately, the producer of the Deferred does the following steps before returning to the consumer:

  1. Create a new Deferred(); object and keep a reference to it, because it will be needed later when the value is ready.
  2. Setup the conditions to create the value requested (e.g. create a new XMLHttpRequest, set its onreadystatechange).
  3. Return the Deferred object.

Since the value is not yet ready, the consumer attaches a function to the Deferred that will be called when the value is ready. This is not unlike setTimeout, or other similar facilities you may already be familiar with. The consumer can also attach an "errback" to the Deferred, which is a callback for error handling.

When the value is ready, the producer simply calls myDeferred.callback(theValue). If an error occurred, it should call myDeferred.errback(theValue) instead. As soon as this happens, the callback that the consumer attached to the Deferred is called with theValue as the only argument.

There are quite a few additional "advanced" features baked into Deferred, such as cancellation and callback chains, so take a look at the API reference if you would like to know more!

API Reference

Errors

AlreadyCalledError:

Thrown by a Deferred if .callback or .errback are called more than once.

Availability:
Available in MochiKit 1.3.1+

BrowserComplianceError:

Thrown when the JavaScript runtime is not capable of performing the given function. Currently, this happens if the browser does not support XMLHttpRequest.

Availability:
Available in MochiKit 1.3.1+

CancelledError:

Thrown by a Deferred when it is cancelled, unless a canceller is present and throws something else.

Availability:
Available in MochiKit 1.3.1+

GenericError:

Results passed to .fail or .errback of a Deferred are wrapped by this Error if !(result instanceof Error).

Availability:
Available in MochiKit 1.3.1+

XMLHttpRequestError:

Thrown when an XMLHttpRequest does not complete successfully for any reason. The req property of the error is the failed XMLHttpRequest object, and for convenience the number property corresponds to req.status.

Availability:
Available in MochiKit 1.3.1+

Constructors

Deferred():

Encapsulates a sequence of callbacks in response to a value that may not yet be available. This is modeled after the Deferred class from Twisted [3].

Why do we want this? JavaScript has no threads, and even if it did, threads are hard. Deferreds are a way of abstracting non-blocking events, such as the final response to an XMLHttpRequest.

The sequence of callbacks is internally represented as a list of 2-tuples containing the callback/errback pair. For example, the following call sequence:

var d = new Deferred();
d.addCallback(myCallback);
d.addErrback(myErrback);
d.addBoth(myBoth);
d.addCallbacks(myCallback, myErrback);

is translated into a Deferred with the following internal representation:

[
    [myCallback, null],
    [null, myErrback],
    [myBoth, myBoth],
    [myCallback, myErrback]
]

The Deferred also keeps track of its current status (fired). Its status may be one of the following three values:

Value Condition
-1 no value yet (initial condition)
0 success
1 error

A Deferred will be in the error state if one of the following conditions are met:

  1. The result given to callback or errback is "instanceof Error"
  2. The callback or errback threw while executing. If the thrown object is not instanceof Error, it will be wrapped with GenericError.

Otherwise, the Deferred will be in the success state. The state of the Deferred determines the next element in the callback sequence to run.

When a callback or errback occurs with the example deferred chain, something equivalent to the following will happen (imagine that exceptions are caught and returned as-is):

// d.callback(result) or d.errback(result)
if (!(result instanceof Error)) {
    result = myCallback(result);
}
if (result instanceof Error) {
    result = myErrback(result);
}
result = myBoth(result);
if (result instanceof Error) {
    result = myErrback(result);
} else {
    result = myCallback(result);
}

The result is then stored away in case another step is added to the callback sequence. Since the Deferred already has a value available, any new callbacks added will be called immediately.

There are two other "advanced" details about this implementation that are useful:

Callbacks are allowed to return Deferred instances, so you can build complicated sequences of events with (relative) ease.

The creator of the Deferred may specify a canceller. The canceller is a function that will be called if Deferred.prototype.cancel is called before the Deferred fires. You can use this to allow an XMLHttpRequest to be cleanly cancelled, for example. Note that cancel will fire the Deferred with a CancelledError (unless your canceller throws or returns a different Error), so errbacks should be prepared to handle that Error gracefully for cancellable Deferred instances.

Availability:
Available in MochiKit 1.3.1+

Deferred.prototype.addBoth(func):

Add the same function as both a callback and an errback as the next element on the callback sequence. This is useful for code that you want to guarantee to run, e.g. a finalizer.

If additional arguments are given, then func will be replaced with MochiKit.Base.partial.apply(null, arguments). This differs from Twisted, because the result of the callback or errback will be the last argument passed to func.

If func returns a Deferred, then it will be chained (its value or error will be passed to the next callback). Note that once the returned Deferred is chained, it can no longer accept new callbacks.

Availability:
Available in MochiKit 1.3.1+

Deferred.prototype.addCallback(func[, ...]):

Add a single callback to the end of the callback sequence.

If additional arguments are given, then func will be replaced with MochiKit.Base.partial.apply(null, arguments). This differs from Twisted, because the result of the callback will be the last argument passed to func.

If func returns a Deferred, then it will be chained (its value or error will be passed to the next callback). Note that once the returned Deferred is chained, it can no longer accept new callbacks.

Availability:
Available in MochiKit 1.3.1+

Deferred.prototype.addCallbacks(callback, errback):

Add separate callback and errback to the end of the callback sequence. Either callback or errback may be null, but not both.

If callback or errback returns a Deferred, then it will be chained (its value or error will be passed to the next callback). Note that once the returned Deferred is chained, it can no longer accept new callbacks.

Availability:
Available in MochiKit 1.3.1+

Deferred.prototype.addErrback(func):

Add a single errback to the end of the callback sequence.

If additional arguments are given, then func will be replaced with MochiKit.Base.partial.apply(null, arguments). This differs from Twisted, because the result of the errback will be the last argument passed to func.

If func returns a Deferred, then it will be chained (its value or error will be passed to the next callback). Note that once the returned Deferred is chained, it can no longer accept new callbacks.

Availability:
Available in MochiKit 1.3.1+

Deferred.prototype.callback([result]):

Begin the callback sequence with a non-Error result. Result may be any value except for a Deferred.

Either .callback or .errback should be called exactly once on a Deferred.

Availability:
Available in MochiKit 1.3.1+

Deferred.prototype.cancel():

Cancels a Deferred that has not yet received a value, or is waiting on another Deferred as its value.

If a canceller is defined, the canceller is called. If the canceller did not return an Error, or there was no canceller, then the errback chain is started with CancelledError.

Availability:
Available in MochiKit 1.3.1+

Deferred.prototype.errback([result]):

Begin the callback sequence with an error result. Result may be any value except for a Deferred, but if !(result instanceof Error), it will be wrapped with GenericError.

Either .callback or .errback should be called exactly once on a Deferred.

Availability:
Available in MochiKit 1.3.1+

DeferredLock():

A lock for asynchronous systems.

The locked property of a DeferredLock will be true if it locked, false otherwise. Do not change this property.

Availability:
Available in MochiKit 1.3.1+

DeferredLock.prototype.acquire():

Attempt to acquire the lock. Returns a Deferred that fires on lock acquisition with the DeferredLock as the value. If the lock is locked, then the Deferred goes into a waiting list.

Availability:
Available in MochiKit 1.3.1+

DeferredLock.prototype.release():

Release the lock. If there is a waiting list, then the first Deferred in that waiting list will be called back.

Availability:
Available in MochiKit 1.3.1+

DeferredList(list, [fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller]):

Combine a list of Deferred into one. Track the callbacks and return a list of (success, result) tuples, 'success' being a boolean indicating whether result is a normal result or an error.

Once created, you have access to all Deferred methods, like addCallback, addErrback, addBoth. The behaviour can be changed by the following options:

fireOnOneCallback:
Flag for launching the callback once the first Deferred of the list has returned.
fireOnOneErrback:
Flag for calling the errback at the first error of a Deferred.
consumeErrors:
Flag indicating that any errors raised in the Deferreds should be consumed by the DeferredList.

Example:

// We need to fetch data from 2 different urls
var d1 = loadJSONDoc(url1);
var d2 = loadJSONDoc(url2);
var l1 = new DeferredList([d1, d2], false, false, true);
l1.addCallback(function (resultList) {
    MochiKit.Base.map(function (result) {
        if (result[0]) {
            alert("Data is here: " + result[1]);
        } else {
            alert("Got an error: " + result[1]);
        }
    }, resultList);
});
Availability:
Available in MochiKit 1.3.1+

Functions

callLater(seconds, func[, args...]):

Call func(args...) after at least seconds seconds have elapsed. This is a convenience method for:

func = partial.apply(extend(null, arguments, 1));
return wait(seconds).addCallback(function (res) { return func() });

Returns a cancellable Deferred.

Availability:
Available in MochiKit 1.3.1+

doXHR(url[, {option: value, ...}]):

Perform a customized XMLHttpRequest and wrap it with a Deferred that may be cancelled.

Note that only 200 (OK), 201 (CREATED), 204 (NO CONTENT) and 304 (NOT MODIFIED) are considered success codes. All other status codes will result in an errback with an XMLHttpRequestError.

url:
The URL for this request.

The following options are currently accepted:

method:
The HTTP method. Default is 'GET'.
sendContent:
The content to send (e.g. with POST). Default is no content.
queryString:
If present it will be used to build a query string to append to the url using MochiKit.Base.queryString. Default is no query string.
username:
The username for the request. Default is no username.
password:
The password for the request. Default is no password.
headers:
Additional headers to set in the request, either as an object such as {'Accept': 'text/xml'} or as an Array of 2-Arrays [['Accept', 'text/xml']]. Default is no additional headers.
mimeType:
An override mime type. The typical use of this is to pass 'text/xml' to force XMLHttpRequest to attempt to parse responseXML. Default is no override.
returns:
Deferred that will callback with the XMLHttpRequest instance on success
Availability:
Available in MochiKit 1.4+.

doSimpleXMLHttpRequest(url[, queryArguments...]):

Perform a simple XMLHttpRequest and wrap it with a Deferred that may be cancelled.

Note that only 200 (OK), 201 (CREATED), 204 (NO CONTENT) and 304 (NOT MODIFIED) are considered success codes. All other status codes will result in an errback with an XMLHttpRequestError.

url:
The URL to GET
queryArguments:

If this function is called with more than one argument, a "?" and the result of MochiKit.Base.queryString with the rest of the arguments are appended to the URL.

For example, this will do a GET request to the URL http://example.com?bar=baz:

doSimpleXMLHttpRequest("http://example.com", {bar: "baz"});
returns:
Deferred that will callback with the XMLHttpRequest instance on success
Availability:
Available in MochiKit 1.3.1+. Support for 201 and 204 were added in MochiKit 1.4.

evalJSONRequest(req):

Evaluate a JSON [4] XMLHttpRequest

req:
The request whose .responseText property is to be evaluated. If the JSON is wrapped in a comment, the comment will be stripped before evaluation.
returns:
A JavaScript object
Availability:
Available in MochiKit 1.3.1+

fail([result]):

Return a Deferred that has already had .errback(result) called.

See succeed documentation for rationale.

result:
The result to give to Deferred.prototype.errback(result).
returns:
A new Deferred()
Availability:
Available in MochiKit 1.3.1+

gatherResults(deferreds):

A convenience function that returns a DeferredList from the given Array of Deferred instances that will callback with an Array of just results when they're available, or errback on the first array.

Availability:
Available in MochiKit 1.3.1+

getXMLHttpRequest():

Return an XMLHttpRequest compliant object for the current platform.

In order of preference:

  • new XMLHttpRequest()
  • new ActiveXObject('Msxml2.XMLHTTP')
  • new ActiveXObject('Microsoft.XMLHTTP')
  • new ActiveXObject('Msxml2.XMLHTTP.4.0')
Availability:
Available in MochiKit 1.3.1+

maybeDeferred(func[, argument...]):

Call a func with the given arguments and ensure the result is a Deferred.

func:
The function to call.
returns:
A new Deferred based on the call to func. If func does not naturally return a Deferred, its result or error value will be wrapped by one.
Availability:
Available in MochiKit 1.3.1+

loadJSONDoc(url[, queryArguments...]):

Do a simple XMLHttpRequest to a URL and get the response as a JSON [4] document.

url:
The URL to GET
queryArguments:

If this function is called with more than one argument, a "?" and the result of MochiKit.Base.queryString with the rest of the arguments are appended to the URL.

For example, this will do a GET request to the URL http://example.com?bar=baz:

loadJSONDoc("http://example.com", {bar: "baz"});
returns:
Deferred that will callback with the evaluated JSON [4] response upon successful XMLHttpRequest
Availability:
Available in MochiKit 1.3.1+

sendXMLHttpRequest(req[, sendContent]):

Set an onreadystatechange handler on an XMLHttpRequest object and send it off. Will return a cancellable Deferred that will callback on success.

Note that only 200 (OK), 201 (CREATED), 204 (NO CONTENT) and 304 (NOT MODIFIED) are considered success codes. All other status codes will result in an errback with an XMLHttpRequestError.

req:
An preconfigured XMLHttpRequest object (open has been called).
sendContent:
Optional string or DOM content to send over the XMLHttpRequest.
returns:
Deferred that will callback with the XMLHttpRequest instance on success.
Availability:
Available in MochiKit 1.3.1+. Support for 201 and 204 were added in MochiKit 1.4.

succeed([result]):

Return a Deferred that has already had .callback(result) called.

This is useful when you're writing synchronous code to an asynchronous interface: i.e., some code is calling you expecting a Deferred result, but you don't actually need to do anything asynchronous. Just return succeed(theResult).

See fail for a version of this function that uses a failing Deferred rather than a successful one.

result:
The result to give to Deferred.prototype.callback(result)
returns:
a new Deferred
Availability:
Available in MochiKit 1.3.1+

wait(seconds[, res]):

Return a new cancellable Deferred that will .callback(res) after at least seconds seconds have elapsed.

Availability:
Available in MochiKit 1.3.1+

See Also

[1]AJAX, Asynchronous JavaScript and XML: http://en.wikipedia.org/wiki/AJAX
[2]Twisted, an event-driven networking framework written in Python: http://twistedmatrix.com/
[3]Twisted Deferred Reference: http://twistedmatrix.com/projects/core/documentation/howto/defer.html
[4](1, 2, 3) JSON, JavaScript Object Notation: http://json.org/

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Style.html0000660000175000017500000005007211113647640017512 0ustar scottscott MochiKit.Style - painless Style manipulation API MochiKit Back to docs index

Name

MochiKit.Style - painless Style manipulation API

Synopsis

var messagePos = getElementPosition('message');
var messageSize = getElementDimensions('message');

var notifyPos = new MochiKit.Style.Coordinates(
     messagePos.x + messageSize.w + 10,
     messagePos.y);

setElementPosition('notify', notifyPos);

Description

Refactored from MochiKit.DOM.

Overview

Refactored from MochiKit.DOM.

Element Visibility

The hideElement and showElement functions are provided as a convenience, but only work for elements that are display: block. For a general solution to showing, hiding, and checking the explicit visibility of elements, we recommend using a solution that involves a little CSS. Here's an example:

<style type="text/css">
    .invisible { display: none; }
</style>

<script type="text/javascript">
    function toggleVisible(elem) {
        toggleElementClass("invisible", elem);
    }

    function makeVisible(elem) {
        removeElementClass(elem, "invisible");
    }

    function makeInvisible(elem) {
        addElementClass(elem, "invisible");
    }

    function isVisible(elem) {
        // you may also want to check for
        // getElement(elem).style.display == "none"
        return !hasElementClass(elem, "invisible");
    };
</script>

MochiKit doesn't ship with such a solution, because there is no reliable and portable method for adding CSS rules on the fly with JavaScript.

API Reference

Functions

getStyle(element, cssSelector):

Looks up a CSS property for the given element. The element can be specified as either a string with the element's ID or the element object itself.

cssSelector:
The CSS selector, e.g. background-color.
Availability:
Available in MochiKit 1.4+

setStyle(element, styles):

Set CSS properties on a the given element. The element can be specified as either a string with the element's ID or the element object itself.

styles:
Dictionnary holding CSS properties to set, e.g. {'background-color': 'red', 'opacity': 0.5}.
Availability:
Available in MochiKit 1.4+

setOpacity(element, opacity):

Sets opacity for element. Valid opacity values range from 0 (invisible) to 1 (opaque). element is looked up with getElement, so string identifiers are also acceptable.

Availability:
Available in MochiKit 1.4+

getElementDimensions(element[, contentSize=false]):

Return the absolute pixel width and height of element as an object with w and h properties, or undefined if element is not in the document. The size will include padding and border, but not margins, unless contentSize is set to true, in which case the size will be only the content size, without padding and border. element may be specified as a string to be looked up with getElement, a DOM element, or trivially as an object with w and/or h properties.

Availability:
Available in MochiKit 1.4+

setElementDimensions(element, dimensions[, units='px']):

Sets the dimensions of element in the document from an object with w and h properties.

Warning: IE in quirks-mode seems to behave strange when you set the height off an element containing text to 0. You can workaround this by setting the value of visibly/display.

element:
A reference to the DOM element to update (if a string is given, getElement(node) will be used to locate the node)
dimensions:
An object with w and h properties. You can also specify only one property.
units:
Optionally set the units to use, default is px
Availability:
Available in MochiKit 1.4+

getElementPosition(element[, relativeTo={x: 0, y: 0}]):

Return the absolute pixel position of element in the document as an object with x and y properties, or undefined if element is not in the document. element may be specified as a string to be looked up with getElement, a DOM element, or trivially as an object with x and/or y properties.

If relativeTo is given, then its coordinates are subtracted from the absolute position of element, e.g.:

var elemPos = getElementPosition(elem);
var anotherElemPos = getElementPosition(anotherElem);
var relPos = getElementPosition(elem, anotherElem);
assert( relPos.x == (elemPos.x - anotherElemPos.x) );
assert( relPos.y == (elemPos.y - anotherElemPos.y) );

relativeTo may be specified as a string to be looked up with getElement, a DOM element, or trivially as an object with x and/or y properties.

Availability:
Available in MochiKit 1.4+

setElementPosition(element, position[, units='px']):

Sets the absolute position of element in the document from an object with x and y properties.

element:
A reference to the DOM element to update (if a string is given, getElement(node) will be used to locate the node)
position:
An object with x and y properties. You can also specify only one property.
units:
Optionally set the units to use, default is px
Availability:
Available in MochiKit 1.4+

makePositioned(element):

Ensure that element.style.position is set to "relative" if it is not set or is "static". If element is a string, then it will be looked up with getElement.

Availability:
Available in MochiKit 1.4.1+

undoPositioned(element):

Restore the setting of element.style.position set by makePositioned(element). If element is a string, then it will be looked up with getElement.

Availability:
Available in MochiKit 1.4.1+

makeClipping(element):

Ensure that element.style.overflow = 'hidden'. If element is a string, then it will be looked up with getElement.

Returns the original values of overflow, overflow-y and overflow-y so that they may be restored with undoClipping(element, overflow).

Availability:
Available in MochiKit 1.4.1+

undoClipping(element, overflow):

Restore the setting of element.style.overflow set by makeClipping(element). If element is a string, then it will be looked up with getElement.

Availability:
Available in MochiKit 1.4.1+

setDisplayForElement(display, element[, ...]):

Change the style.display for the given element(s). Usually used as the partial forms:

Elements are looked up with getElement, so string identifiers are acceptable.

For information about the caveats of using a style.display based show/hide mechanism, and a CSS based alternative, see Element Visibility.

Availability:
Available in MochiKit 1.4+

showElement(element, ...):

Partial form of setDisplayForElement, specifically:

partial(setDisplayForElement, "block")

For information about the caveats of using a style.display based show/hide mechanism, and a CSS based alternative, see Element Visibility.

Availability:
Available in MochiKit 1.4+

hideElement(element, ...):

Partial form of setDisplayForElement, specifically:

partial(setDisplayForElement, "none")

For information about the caveats of using a style.display based show/hide mechanism, and a CSS based alternative, see Element Visibility.

Availability:
Available in MochiKit 1.4+

getViewportDimensions():

Return the pixel width and height of the viewport as an object with w and h properties.

Availability:
Available in MochiKit 1.4+

getViewportPosition():

Return the pixel position of the viewport inside the window, as a Coordinates object.

Availability:
Available in MochiKit 1.4+

Objects

Coordinates(x, y):

Constructs an object with x and y properties. obj.toString() returns something like {x: 0, y: 42} for debugging.

Availability:
Available in MochiKit 1.4+

Dimensions(w, h):

Constructs an object with w and h properties. obj.toString() returns something like {w: 0, h: 42} for debugging.

Availability:
Available in MochiKit 1.4+

Authors

Copyright

Copyright 2005-2006 Bob Ippolito <bob@redivi.com>, and Beau Hartshorne <beau@hartshornesoftware.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Sortable.html0000660000175000017500000002174511113647640020172 0ustar scottscott MochiKit.Sortable - sortable with drag and drop lists MochiKit Back to docs index

Name

MochiKit.Sortable - sortable with drag and drop lists

Synopsis

<ul id="dnd_sortable">
    <li>mochibot.com</li>
    <li>pythonmac.org</li>
    <li>undefined.org</li>
    <li>python.org</li>
</ul>
<script type="text/javascript">
  MochiKit.Sortable.Sortable.create('dnd_sortable');
</script>

Description

MochiKit.Sortable add a new Sortable object to manipulate easily drag&drop in lists.

Overview

MochiKit.Sortable mainly contains the Sortable object offering facilities to manipulate a list and drag its items to reorder it. It can also be serialized for being send to server. It is ported from Scriptaculous.

API Reference

Objects defined

SortableObserver:

Observer for DragAndDrop object. You normally don't have to access this, only for customization purpose.

Availability:
Available in MochiKit 1.4+

Sortable.create(element [, options]):

Create a new Sortable. Usually you'll call it with a UL element, but it can be customized with options to use something else.

You have the following options:

element element
tag 'li'
dropOnEmpty false
overlap 'vertical'
constraint 'vertical'
containment element
handle false
only false
hoverclass null
ghosting false
scroll false
scrollSensitivity 20
scrollSpeed 15
format /^[^_]*_(.*)$/
onChange MochiKit.Base.noop
onUpdate MochiKit.Base.noop
tree false
treeTag 'ul'
tag:
Name of the tag used to make the draggable elements. It matches all the childNodes of the Sortable element with this tag.
only:
Class or array of classes used to filter the children, combined with the tag criteria.
format:
Regular expression which serves as a match filter for serialization, on children' ids. For example, with the default value, you'll get ['1', '2', '3', '4'] with ids ['sort_1', 'sort_2', 'sort_3', 'sort_4'].
onChange:
Callback called when an element moves between others in the Sortable. It's called for each movements, even if you don't release the mouse.
onUpdate:
Callback called when the order changes in the Sortable. It's called only if the Sortable is modified, after you dropped an element.
tree:
Option for creating a Sortable tree. It's an experimental setting, that can be very slow even with a few elements. You can customize its behaviour with the treeTag option, that defines the node used to make branches in your tree (that contains leaves).

Other options are passed to the Draggables and Droppables objects created. Refer to MochiKit.DragAndDrop for more information.

A bug with Internet Explorer rendering engine can cause a problem with the default effect used on start (the symptom being that the rows vanish). If you encounter this problem, pass MochiKit.Base.noop as the starteffect option.

Availability:
Available in MochiKit 1.4+

Sortable.destroy(element):

Destroy a previously created sortable. It prevents further use of the Sortable functionnality on the element, unless recreated.

Availability:
Available in MochiKit 1.4+

Sortable.serialize(element [, options]):

Serialize the content of a Sortable. Useful to send this content through a XMLHTTPRequest. The options overrides the ones of the Sortable only for the serialization.

tag tag from the Sortable
only only from the Sortable
name id of the element
format format of the Sortable or /^[^_]*_(.*)$
Availability:
Available in MochiKit 1.4+

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

Portions adapted from Scriptaculous are available under the terms of the MIT License.

MochiKit-1.4.2/doc/html/MochiKit/Signal.html0000660000175000017500000007025411113647640017633 0ustar scottscott MochiKit.Signal - Simple universal event handling MochiKit Back to docs index

Name

MochiKit.Signal - Simple universal event handling

Synopsis

Signal for DOM events:

// DOM events are also signals. Connect freely! The functions will be
// called with the custom event as a parameter.

// calls myClicked.apply(getElement('myID'), [event])
connect('myID', 'onclick', myClicked);

// calls wasClicked.apply(myObject, [event])
connect('myID', 'onclick', myObject, wasClicked);

// calls myObject.wasClicked(event)
connect('myID', 'onclick', myObject, 'wasClicked');

// the event is normalized, no more e = e || window.event!
myObject.wasClicked = function(e) {
    var crossBrowserCoordinates = e.mouse().page;
    // e.mouse().page is a MochiKit.Style.Coordinates object
}

Signal for non-DOM events:

// otherObject.gotFlash() will be called when 'flash' signalled.
connect(myObject, 'flash', otherObject, 'gotFlash');

// gotBang.apply(otherObject, [...]) will be called when 'bang' signalled.
// You can access otherObject from within gotBang as 'this'.
connect(myObject, 'bang', otherObject, gotBang);

// myFunc.apply(myObject, [...]) will be called when 'flash' signalled.
// You can access myObject from within myFunc as 'this'.
var ident = connect(myObject, 'flash', myFunc);

// You may disconnect with the return value from connect
disconnect(ident);

// Signal can take parameters. These will be passed along to the
// connected functions.
signal(myObject, 'flash');
signal(myObject, 'bang', 'BANG!');

Description

Event handling was never so easy!

This module takes care of all the hard work—figuring out which event model to use, trying to retrieve the event object, and handling your own internal events, as well as cleanup when the page is unloaded to clean up IE's nasty memory leakage.

This event system is largely based on Qt's signal/slot system. Read more on how that is handled and also how it is used in model/view programming at: http://doc.trolltech.com/

Overview

Using Signal for DOM Events

When using MochiKit.Signal, do not use the browser's native event API. That means, no onclick="blah", no elem.addEventListener(...), and certainly no elem.attachEvent(...). This also means that MochiKit.DOM.addToCallStack and MochiKit.DOM.addLoadEvent should not be used in combination with this module.

Signals for DOM objects are named with the 'on' prefix, e.g.: 'onclick', 'onkeyup', etc.

When the signal fires, your slot will be called with one parameter, the custom event object.

Custom Event Objects for DOM events

Signals triggered by DOM events are called with a custom event object as a parameter. The custom event object presents a consistent view of the event across all supported platforms and browsers, and provides many conveniences not available even in a correct W3C implementation.

See the DOM Custom Event Object Reference for a detailed API description of this object.

If you find that you're accessing the native event for any reason, create a new ticket and we'll look into normalizing the behavior you're looking for.

Memory Usage

Any object that has connected slots (via connect()) is referenced by the Signal mechanism until it is disconnected via disconnect() or disconnectAll().

Signal does not leak. It registers an 'onunload' event that disconnects all objects on the page when the browser leaves the page. However, memory usage will grow during the page view for every connection made until it is disconnected. Even if the DOM object is removed from the document, it will still be referenced by Signal until it is explicitly disconnected.

In order to conserve memory during the page view, disconnectAll() any DOM elements that are about to be removed from the document.

Synthesized Events

Certain events supported by MochiKit are not generated natively by all browsers. MochiKit can synthesize these events even for non-supporting browsers, however, by watching for related events and triggering the appropriate signals at the right times.

These events include:

onmouseenter

Similar to 'onmouseover', but does not "bubble" up to parent nodes. Such bubbling is often a cause of confusion. On an 'onmouseenter' event, you can be certain that the mouse has left the node attached to the event.

Availability:
Available in MochiKit 1.4+

onmouseleave

Similar to 'onmouseout', but does not "bubble" up to parent nodes. This is the analog to 'onmouseenter'.

Availability:
Available in MochiKit 1.4+

onmousewheel

Not strictly synthesized, but named 'DOMMouseScroll' in Gecko-based browsers. MochiKit translates 'onmousewheel' to the corresponding event in these browsers.

Availability:
Available in MochiKit 1.4+

Using Signal for non-DOM objects

Signals are triggered with the signal(src, 'signal', ...) function. Additional parameters passed to this are passed onto the connected slots. Explicit signals are not required for DOM events.

Slots that are connected to a signal are called in the following manner when that signal is signalled:

  • If the slot was a single function, then it is called with this set to the object originating the signal with whatever parameters it was signalled with.
  • If the slot was an object and a function, then it is called with this set to the object, and with whatever parameters it was signalled with.
  • If the slot was an object and a string, then object[string] is called with the parameters to the signal.

API Reference

Signal API Reference

connect(src, signal, dest[, func]):

Connects a signal to a slot, and return a unique identifier that can be used to disconnect that signal.

src is the object that has the signal. You may pass in a string, in which case, it is interpreted as an id for an HTML element.

signal is a string that represents a signal name. If 'src' is an HTML Element, window, or the document, then it can be one of the 'on-XYZ' events. You must include the 'on' prefix, and it must be all lower-case.

dest and func describe the slot, or the action to take when the signal is triggered.

  • If dest is an object and func is a string, then dest[func].apply(dest, [...]) will be called when the signal is signalled.
  • If dest is an object and func is a function, then func.apply(dest, [...]) will be called when the signal is signalled.
  • If func is undefined and dest is a function, then dest.apply(src, [...]) will be called when the signal is signalled.

No other combinations are allowed and will raise an exception.

The return value can be passed to disconnect to disconnect the signal.

In MochiKit 1.4+, if src is an object that has a __connect__ method, then src.__connect__(ident, signal, objOrFunc, funcOrStr) will be called. The __connect__ method is allowed to disconnect the signal. DOM objects can not implement this feature.

Availability:
Available in MochiKit 1.3.1+

disconnect(ident):

To disconnect a signal, pass its ident returned by connect(). This is similar to how the browser's setTimeout and clearTimeout works.

In MochiKit 1.4+, if the signal source is an object that has a __disconnect__ method, then src.__disconnect__(ident, signal, objOrFunc, funcOrStr) will be called. DOM objects can not implement this feature.

Availability:
Available in MochiKit 1.3.1+

disconnectAll(src[, signal, ...]):

Removes a set of signals from src, similar to calling disconnect(ident) for each one.

disconnectAll(src) removes all signals from src.

disconnectAll(src, 'onmousedown', 'mySignal') will remove all 'onmousedown' and 'mySignal' signals from src.

Availability:
Available in MochiKit 1.3.1+

disconnectAllTo(dest[, func]):

Removes a set of signals connected to dest, similar to calling disconnect(ident) for each one.

disconnectAllTo(dest) removes all signals connected to dest.

disconnectAllTo(dest, func) will remove all signals connected to dest using func.

Availability:
Available in MochiKit 1.4+

signal(src, signal, ...):

This will signal a signal, passing whatever additional parameters on to the connected slots. src and signal are the same as for connect().

Availability:
Available in MochiKit 1.3.1+

DOM Custom Event Object Reference

event():

The native event produced by the browser. You should not need to use this.

Availability:
Available in MochiKit 1.3.1+

src():

The element that this signal is connected to.

Availability:
Available in MochiKit 1.3.1+

type():

The event type ('click', 'mouseover', 'keypress', etc.) as a string. Does not include the 'on' prefix.

Availability:
Available in MochiKit 1.3.1+

target():

The element that triggered the event. This may be a child of src().

Availability:
Available in MochiKit 1.3.1+

modifier():

Returns {shift, ctrl, meta, alt, any}, where each property is true if its respective modifier key was pressed, false otherwise. any is true if any modifier is pressed, false otherwise.

Availability:
Available in MochiKit 1.3.1+

stopPropagation():

Works like W3C's stopPropagation().

Availability:
Available in MochiKit 1.3.1+

preventDefault():

Works like W3C's preventDefault().

Availability:
Available in MochiKit 1.3.1+

stop():

Shortcut that calls stopPropagation() and preventDefault().

Availability:
Available in MochiKit 1.3.1+

key():

Returns {code, string}.

Use 'onkeydown' and 'onkeyup' handlers to detect control characters such as 'KEY_F1'. Use the 'onkeypress' handler to detect "printable" characters, such as 'é'.

When a user presses F1, in 'onkeydown' and 'onkeyup' this method returns {code: 122, string: 'KEY_F1'}. In 'onkeypress', it returns {code: 0, string: ''}.

If a user presses Shift+2 on a US keyboard, this method returns {code: 50, string: 'KEY_2'} in 'onkeydown' and 'onkeyup'. In 'onkeypress', it returns {code: 64, string: '@'}.

See _specialKeys in the source code for a comprehensive list of control characters.

Availability:
Available in MochiKit 1.3.1+

mouse():

Properties for 'onmouse*', 'onclick', 'ondblclick', and 'oncontextmenu':

  • page is a MochiKit.Style.Coordinates object that represents the cursor position relative to the HTML document. Equivalent to pageX and pageY in Safari, Mozilla, and Opera.
  • client is a MochiKit.Style.Coordinates object that represents the cursor position relative to the visible portion of the HTML document. Equivalent to clientX and clientY on all browsers. Current versions of Safari incorrectly return clientX as relative to the canvas instead of relative to the viewport (Safari Bug 8707).

Properties for 'onmouseup', 'onmousedown', 'onclick', and 'ondblclick':

  • mouse().button returns {left, right, middle} where each property is true if the mouse button was pressed, false otherwise.

Properties for 'onmousewheel':

  • mouse().wheel is a MochiKit.Style.Coordinates object containing the scroll wheel offset. The number will be positive when scrolling down (or to the right) and negative when scrolling up (or to the left). Note that only Safari 3 currently supports horizontal scrolling. In other browsers, the 'y' component will contain the scroll offset for both directions.

Known browser bugs:

  • Current versions of Safari won't signal 'ondblclick' when attached via connect() (Safari Bug 7790).

  • In Safari < 2.0.4, calling preventDefault() or stop() in 'onclick' events signalled from <a> tags does not prevent the browser from following those links.

  • Mac browsers don't report right-click consistently. Firefox signals the slot and sets modifier().ctrl to true, Opera signals the slot and sets modifier().meta to true, and Safari doesn't signal the slot at all (Safari Bug 6595).

    To find a right-click in Safari, Firefox, and IE, you can connect an element to 'oncontextmenu'. This doesn't work in Opera.

Availability:
Available in MochiKit 1.3.1+

relatedTarget():

Returns the document element that the mouse has moved to. This is generated for 'onmouseover' and 'onmouseout' events.

Availability:
Available in MochiKit 1.3.1+

confirmUnload(msg):

In browsers that support the 'onbeforeunload' event (IE and Firefox), calling this in the event handler will show a dialog box that allows the user to confirm or cancel the navigation away from the page.

Availability:
Available in MochiKit 1.4+

Authors

Copyright

Copyright 2006 Jonathan Gardner <jgardner@jonathangardner.net>, Beau Hartshorne <beau@hartshornesoftware.com>, and Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Logging.html0000660000175000017500000004442511113647640020005 0ustar scottscott MochiKit.Logging - we're all tired of alert() MochiKit Back to docs index

Name

MochiKit.Logging - we're all tired of alert()

Synopsis

log("INFO messages are so boring");
logDebug("DEBUG messages are even worse");
log("good thing I can pass", objects, "conveniently");

Description

MochiKit.Logging steals some ideas from Python's logging module [1], but completely forgot about the Java [2] inspiration. This is a KISS module for logging that provides enough flexibility to do just about anything via listeners, but without all the cruft.

Overview

Native Console Logging

As of MochiKit 1.3, the default logger will log all messages to your browser's native console. This is currently supported in Safari, Opera 9, and Firefox when the FireBug extension is installed. MochiKit 1.4 adds support for the relevant APIs for Internet Explorer (the Debugger and the Atlas framework, see here).

To disable this behavior:

MochiKit.Logging.logger.useNativeConsole = false;

Bookmarklet Based Debugging

JavaScript is at a serious disadvantage without a standard console for "print" statements. Everything else has one. The closest thing that you get in a browser environment is the alert function, which is absolutely evil.

This leaves you with one reasonable solution: do your logging in the page somehow. The problem here is that you don't want to clutter the page with debugging tools. The solution to that problem is what we call BBD, or Bookmarklet Based Debugging [3].

Simply create a bookmarklet for javascript:MochiKit.Logging.logger.debuggingBookmarklet(), and whack it whenever you want to see what's in the logger. Of course, this means you must drink the MochiKit.Logging kool-aid. It's tangy and sweet, don't worry.

Currently this uses MochiKit.LoggingPane if loaded and otherwise falls back to ugly alert messages.

API Reference

Constructors

LogMessage(num, level, info):

Properties:

num:
Identifier for the log message
level:
Level of the log message ("INFO", "WARN", "DEBUG", etc.)
info:
All other arguments passed to log function as an Array
timestamp:
Date object timestamping the log message
Availability:
Available in MochiKit 1.3.1+

Logger([maxSize]):

A basic logger object that has a buffer of recent messages plus a listener dispatch mechanism for "real-time" logging of important messages.

maxSize is the maximum number of entries in the log. If maxSize >= 0, then the log will not buffer more than that many messages. So if you don't like logging at all, be sure to pass 0.

There is a default logger available named "logger", and several of its methods are also global functions:

logger.log -> log
logger.debug -> logDebug
logger.warning -> logWarning
logger.error -> logError
logger.fatal -> logFatal
Availability:
Available in MochiKit 1.3.1+

Logger.prototype.addListener(ident, filter, listener):

Add a listener for log messages.

ident is a unique identifier that may be used to remove the listener later on.

filter can be one of the following:

null:
listener(msg) will be called for every log message received.
string:
logLevelAtLeast(filter) will be used as the function (see below).
function:
filter(msg) will be called for every msg, if it returns true then listener(msg) will be called.

listener is a function that takes one argument, a log message. A log message is an object (LogMessage instance) that has at least these properties:

num:
A counter that uniquely identifies a log message (per-logger)
level:
A string or number representing the log level. If string, you may want to use LogLevel[level] for comparison.
info:
An Array of objects passed as additional arguments to the log function.
Availability:
Available in MochiKit 1.3.1+

Logger.prototype.baseLog(level, message[, ...]):

The base functionality behind all of the log functions. The first argument is the log level as a string or number, and all other arguments are used as the info list.

This function is available partially applied as:

Logger.debug 'DEBUG'
Logger.log 'INFO'
Logger.error 'ERROR'
Logger.fatal 'FATAL'
Logger.warning 'WARNING'

For the default logger, these are also available as global functions, see the Logger constructor documentation for more info.

Availability:
Available in MochiKit 1.3.1+

Logger.prototype.clear():

Clear all messages from the message buffer.

Availability:
Available in MochiKit 1.3.1+

Logger.prototype.debuggingBookmarklet():

Display the contents of the logger in a useful way for browsers.

Currently, if MochiKit.LoggingPane is loaded, then a pop-up MochiKit.LoggingPane.LoggingPane will be used. Otherwise, it will be an alert with Logger.prototype.getMessageText().

Availability:
Available in MochiKit 1.3.1+

Logger.prototype.dispatchListeners(msg):

Dispatch a log message to all listeners.

Availability:
Available in MochiKit 1.3.1+

Logger.prototype.getMessages([howMany]):

Returns a list of messages from the message buffer, ordered from the oldest to the newest message. If howMany is specified, only the last howMany messages are returned. Otherwise all messages in the buffer are returned.

Availability:
Available in MochiKit 1.3.1+

Logger.prototype.getMessageText([howMany]):

Get a string representing up to the last howMany messages in the message buffer. The default is 30.

The message looks like this:

LAST {messages.length} MESSAGES:
  [{msg.num}] {msg.level}: {m.info.join(' ')}
  [{msg.num}] {msg.level}: {m.info.join(' ')}
  ...

If you want some other format, use Logger.prototype.getMessages and do it yourself.

Availability:
Available in MochiKit 1.3.1+

Logger.prototype.removeListener(ident):

Remove a listener using the ident given to Logger.prototype.addListener

Availability:
Available in MochiKit 1.3.1+

Functions

alertListener(msg):

Ultra-obnoxious alert(...) listener

Availability:
Available in MochiKit 1.3.1+

log(message[, info[, ...]]):

Log an INFO message to the default logger

Availability:
Available in MochiKit 1.3.1+

logDebug(message[, info[, ...]]):

Log a DEBUG message to the default logger

Availability:
Available in MochiKit 1.3.1+

logError(message[, info[, ...]]):

Log an ERROR message to the default logger

Availability:
Available in MochiKit 1.3.1+

logFatal(message[, info[, ...]]):

Log a FATAL message to the default logger

Availability:
Available in MochiKit 1.3.1+

logLevelAtLeast(minLevel):

Return a function that will match log messages whose level is at least minLevel

Availability:
Available in MochiKit 1.3.1+

logWarning(message[, info[, ...]]):

Log a WARNING message to the default logger

Availability:
Available in MochiKit 1.3.1+

See Also

[1]Python's logging module: http://docs.python.org/lib/module-logging.html
[2]PEP 282, where they admit all of the Java influence: http://www.python.org/peps/pep-0282.html
[3]Original Bookmarklet Based Debugging blather: http://bob.pythonmac.org/archives/2005/07/03/bookmarklet-based-debugging/

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Iter.html0000660000175000017500000005454711113647640017330 0ustar scottscott MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy MochiKit Back to docs index

Name

MochiKit.Iter - itertools for JavaScript; iteration made HARD, and then easy

Synopsis

theSum = sum(takewhile(
        partial(operator.gt, 10),
        imap(
            partial(operator.mul, 2),
            count()
        )
    )
));

assert( theSum == (0 + 0 + 2 + 4 + 6 + 8) );

Description

All of the functional programming missing from MochiKit.Base lives here. The functionality in this module is largely inspired by Python's iteration protocol [1], and the itertools module [2].

MochiKit.Iter defines a standard way to iterate over anything, that you can extend with registerIteratorFactory, or by implementing the .iter() or .__iterator__() (in MochiKit 1.4+) protocol. Iterators are lazy, so it can potentially be cheaper to build a filter chain of iterators than to build lots of intermediate arrays. Especially when the data set is very large, but the result is not.

Overview

Iteration for JavaScript

The best overview right now is in my Iteration for JavaScript [3] blog entry. This information will migrate here eventually.

API Reference

Errors

StopIteration:

The singleton MochiKit.Base.NamedError that signifies the end of an iterator

Availability:
Available in MochiKit 1.3.1+

Functions

applymap(fun, seq[, self]):

applymap(fun, seq) --> fun.apply(self, seq0), fun.apply(self, seq1), ...

Availability:
Available in MochiKit 1.3.1+

chain(p, q[, ...]):

chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ...

Availability:
Available in MochiKit 1.3.1+

count(n=0):

count(n=0) --> n, n + 1, n + 2, ...

Availability:
Available in MochiKit 1.3.1+

cycle(p):

cycle(p) --> p0, p1, ... plast, p0, p1, ...

Availability:
Available in MochiKit 1.3.1+

dropwhile(pred, seq):

dropwhile(pred, seq) --> seq[n], seq[n + 1], starting when pred(seq[n]) fails

Availability:
Available in MochiKit 1.3.1+

every(iterable, func):

Return true if func(item) is true for every item in iterable.

Availability:
Available in MochiKit 1.3.1+

exhaust(iterable):

Exhausts an iterable without saving the results anywhere, like list(iterable) when you don't care what the output is.

Availability:
Available in MochiKit 1.3.1+

forEach(iterable, func[, self]):

Call func for each item in iterable, and don't save the results.

Availability:
Available in MochiKit 1.3.1+

groupby(iterable[, keyfunc]):

Make an iterator that returns consecutive keys and groups from the iterable. The key is a function computing a key value for each element. If not specified or is None, key defaults to an identity function and returns the element unchanged. Generally, the iterable needs to already be sorted on the same key function.

The returned group is itself an iterator that shares the underlying iterable with groupby(). Because the source is shared, when the groupby object is advanced, the previous group is no longer visible. So, if that data is needed later, it should be stored as an array:

var groups = [];
var uniquekeys = [];
forEach(groupby(data, keyfunc), function (key_group) {
    groups.push(list(key_group[1]));
    uniquekeys.push(key_group[0]);
});

As a convenience, groupby_as_array() is provided to suit the above use case.

Availability:
Available in MochiKit 1.3.1+

groupby_as_array(iterable[, keyfunc]):

Perform the same task as groupby(), except return an array of arrays instead of an iterator of iterators.

Availability:
Available in MochiKit 1.3.1+

iextend(lst, iterable):

Just like list(iterable), except it pushes results on lst rather than creating a new one.

Availability:
Available in MochiKit 1.3.1+

ifilter(pred, seq):

ifilter(pred, seq) --> elements of seq where pred(elem) is true

Availability:
Available in MochiKit 1.3.1+

ifilterfalse(pred, seq):

ifilterfalse(pred, seq) --> elements of seq where pred(elem) is false

Availability:
Available in MochiKit 1.3.1+

imap(fun, p, q[, ...]):

imap(fun, p, q, ...) --> fun(p0, q0, ...), fun(p1, q1, ...), ...

Availability:
Available in MochiKit 1.3.1+

islice(seq, [start,] stop[, step]):

islice(seq, [start,] stop[, step]) --> elements from seq[start:stop:step] (in Python slice syntax)

Availability:
Available in MochiKit 1.3.1+

iter(iterable[, sentinel]):

Convert the given argument to an iterator (object implementing .next()).

  1. If iterable is an iterator (implements .next()), then it will be returned as-is.
  2. If iterable is an iterator factory (implements .iter()), then the result of iterable.iter() will be returned.
  3. If iterable is a JavaScript 1.7 iterator factory (implements .__iterable__()), then the result of iterable.__iterable__() will be returned (MochiKit 1.4+).
  4. Otherwise, the iterator factory MochiKit.Base.AdapterRegistry is used to find a match.
  5. If no factory is found, it will throw TypeError

Built-in iterator factories are present for Array-like objects, and objects that implement the iterateNext protocol (e.g. the result of Mozilla's document.evaluate).

When used directly, using an iterator should look like this:

var it = iter(iterable);
try {
    while (var o = it.next()) {
        // use o
    }
} catch (e) {
    if (e != StopIteration) {
        throw e;
    }
    // pass
}

This is ugly, so you should use the higher order functions to work with iterators whenever possible.

Availability:
Available in MochiKit 1.3.1+

izip(p, q[, ...]):

izip(p, q, ...) --> [p0, q0, ...], [p1, q1, ...], ...

Availability:
Available in MochiKit 1.3.1+

list(iterable):

Convert iterable to a new Array

Availability:
Available in MochiKit 1.3.1+

next(iterator):

Return iterator.next()

Availability:
Available in MochiKit 1.3.1+

range([start,] stop[, step]):

Return an iterator containing an arithmetic progression of integers.

range(i, j) returns iter([i, i + 1, i + 2, ..., j - 1])

start (!) defaults to 0. When step is given, it specifies the increment (or decrement). The end point is omitted!

For example, range(4) returns iter([0, 1, 2, 3]). This iterates over exactly the valid indexes for an array of 4 elements.

Availability:
Available in MochiKit 1.3.1+

reduce(fn, iterable[, initial]):

Apply fn(a, b) cumulatively to the items of an iterable from left to right, so as to reduce the iterable to a single value.

For example:

reduce(function (a, b) { return a + b; }, [1, 2, 3, 4, 5])

calculates:

((((1 + 2) + 3) + 4) + 5).

If initial is given, it is placed before the items of the sequence in the calculation, and serves as a default when the sequence is empty.

Note that the above example could be written more clearly as:

reduce(operator.add, [1, 2, 3, 4, 5])

Or even simpler:

sum([1, 2, 3, 4, 5])
Availability:
Available in MochiKit 1.3.1+

registerIteratorFactory(name, check, iterfactory[, override]):

Register an iterator factory for use with the iter function.

check is a function(a) that returns true if a can be converted into an iterator with iterfactory.

iterfactory is a function(a) that returns an object with a .next() method that returns the next value in the sequence.

iterfactory is guaranteed to only be called if check(a) returns a true value.

If override is true, then it will be made the highest precedence iterator factory. Otherwise, the lowest.

Availability:
Available in MochiKit 1.3.1+

repeat(elem[, n]):

repeat(elem, [,n]) --> elem, elem, elem, ... endlessly or up to n times

Availability:
Available in MochiKit 1.3.1+

reversed(iterable):

Return a reversed array from iterable.

Availability:
Available in MochiKit 1.3.1+

some(iterable, func):

Return true if func(item) is true for at least one item in iterable.

Availability:
Available in MochiKit 1.3.1+

sorted(iterable[, cmp]):

Return a sorted array from iterable.

Availability:
Available in MochiKit 1.3.1+

sum(iterable, start=0):

Returns the sum of a sequence of numbers plus the value of parameter start (with a default of 0). When the sequence is empty, returns start.

Equivalent to:

reduce(operator.add, iterable, start);
Availability:
Available in MochiKit 1.3.1+

takewhile(pred, seq):

takewhile(pred, seq) --> seq[0], seq[1], ... until pred(seq[n]) fails

Availability:
Available in MochiKit 1.3.1+

tee(iterable, n=2):

tee(it, n=2) --> [it1, it2, it3, ... itn] splits one iterator into n

Availability:
Available in MochiKit 1.3.1+

See Also

[1]The iteration protocol is described in PEP 234 - Iterators: http://www.python.org/peps/pep-0234.html
[2]Python's itertools module: http://docs.python.org/lib/module-itertools.html
[3]Iteration in JavaScript: http://bob.pythonmac.org/archives/2005/07/06/iteration-in-javascript/

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/doc/html/MochiKit/Color.html0000660000175000017500000011040711113647640017467 0ustar scottscott MochiKit.Color - color abstraction with CSS3 support MochiKit Back to docs index

Name

MochiKit.Color - color abstraction with CSS3 support

Synopsis

// RGB color expressions are supported
assert(
    objEqual(Color.whiteColor(), Color.fromString("rgb(255,100%, 255)"))
);

// So is instantiating directly from HSL or RGB values.
// Note that fromRGB and fromHSL take numbers between 0.0 and 1.0!
assert( objEqual(Color.fromRGB(1.0, 1.0, 1.0), Color.fromHSL(0.0, 0.0, 1.0) );

// Or even SVG color keyword names, as per CSS3!
assert( Color.fromString("aquamarine"), "#7fffd4" );

// NSColor-like colors built in
assert( Color.whiteColor().toHexString() == "#ffffff" );

Description

MochiKit.Color is an abstraction for handling colors and strings that represent colors.

Overview

MochiKit.Color provides an abstraction of RGB, HSL and HSV colors with alpha. It supports parsing and generating of CSS3 colors, and has a full CSS3 (SVG) color table.

All of the functionality in this module is exposed through a Color constructor and its prototype, but a few of its internals are available for direct use at module level.

API Reference

Constructors

Color():

Represents a color. Component values should be integers between 0.0 and 1.0. You should use one of the Color factory functions such as Color.fromRGB, Color.fromHSL, etc. instead of constructing Color objects directly.

Color instances can be compared with MochiKit.Base.compare (though ordering is on RGB, so is not particularly meaningful except for equality), and the default toString implementation returns Color.prototype.toHexString().

Color instances are immutable, and much of the architecture is inspired by AppKit's NSColor [1]

Availability:
Available in MochiKit 1.3.1+

Color.fromBackground(elem):

Returns a Color object based on the background of the provided element. Equivalent to:

c = Color.fromComputedStyle(
    elem, "backgroundColor", "background-color") || Color.whiteColor();
Availability:
Available in MochiKit 1.3.1+

Color.fromComputedStyle(elem, style):

Returns a Color object based on the result of MochiKit.Style.getStyle(elem, style) or null if not found.

Availability:
Available in MochiKit 1.3.1+

Color.fromHexString(hexString):

Returns a Color object from the given hexadecimal color string. For example, "#FFFFFF" would return a Color with RGB values [255/255, 255/255, 255/255] (white).

Availability:
Available in MochiKit 1.3.1+

Color.fromHSL(hue, saturation, lightness, alpha=1.0):

Return a Color object from the given hue, saturation, lightness values. Values should be numbers between 0.0 and 1.0.

If alpha is not given, then 1.0 (completely opaque) will be used.

Alternate form:
Color.fromHSL({h: hue, s: saturation, l: lightness, a: alpha})
Availability:
Available in MochiKit 1.3.1+

Color.fromHSLString(hslString):

Returns a Color object from the given decimal hsl color string. For example, "hsl(0,0%,100%)" would return a Color with HSL values [0/360, 0/360, 360/360] (white).

Availability:
Available in MochiKit 1.3.1+

Color.fromHSV(hue, saturation, value, alpha=1.0):

Return a Color object from the given hue, saturation, value values. Values should be numbers between 0.0 and 1.0.

If alpha is not given, then 1.0 (completely opaque) will be used.

Alternate form:
Color.fromHSV({h: hue, s: saturation, v: value, a: alpha})
Availability:
Available in MochiKit 1.3.1+

Color.fromName(colorName):

Returns a Color object corresponding to the given SVG 1.0 color keyword name [2] as per the W3C CSS3 Color Module [3]. "transparent" is also accepted as a color name, and will return Color.transparentColor().

Availability:
Available in MochiKit 1.3.1+

Color.fromRGB(red, green, blue, alpha=1.0):

Return a Color object from the given red, green, blue, and alpha values. Values should be numbers between 0 and 1.0.

If alpha is not given, then 1.0 (completely opaque) will be used.

Alternate form:
Color.fromRGB({r: red, g: green, b: blue, a: alpha})
Availability:
Available in MochiKit 1.3.1+

Color.fromRGBString(rgbString):

Returns a Color object from the given decimal rgb color string. For example, "rgb(255,255,255)" would return a Color with RGB values [255/255, 255/255, 255/255] (white).

Availability:
Available in MochiKit 1.3.1+

Color.fromText(elem):

Returns a Color object based on the text color of the provided element. Equivalent to:

c = Color.fromComputedStyle(elem, "color") || Color.whiteColor();
Availability:
Available in MochiKit 1.3.1+

Color.fromString(rgbOrHexString):

Returns a Color object from the given RGB, HSL, hex, or name. Will return null if the string can not be parsed by any of these methods.

See Color.fromHexString, Color.fromRGBString, Color.fromHSLString and Color.fromName more information.

Availability:
Available in MochiKit 1.3.1+

Color.namedColors():

Returns an object with properties for each SVG 1.0 color keyword name [2] supported by CSS3 [3]. Property names are the color keyword name in lowercase, and the value is a string suitable for Color.fromString().

Availability:
Available in MochiKit 1.3.1+

Color.prototype.colorWithAlpha(alpha):

Return a new Color based on this color, but with the provided alpha value.

Availability:
Available in MochiKit 1.3.1+

Color.prototype.colorWithHue(hue):

Return a new Color based on this color, but with the provided hue value.

Availability:
Available in MochiKit 1.3.1+

Color.prototype.colorWithSaturation(saturation):

Return a new Color based on this color, but with the provided saturation value (using the HSL color model).

Availability:
Available in MochiKit 1.3.1+

Color.prototype.colorWithLightness(lightness):

Return a new Color based on this color, but with the provided lightness value.

Availability:
Available in MochiKit 1.3.1+

Color.prototype.darkerColorWithLevel(level):

Return a new Color based on this color, but darker by the given level (between 0 and 1.0).

Availability:
Available in MochiKit 1.3.1+

Color.prototype.lighterColorWithLevel(level):

Return a new Color based on this color, but lighter by the given level (between 0 and 1.0).

Availability:
Available in MochiKit 1.3.1+

Color.prototype.blendedColor(other, fraction=0.5):

Return a new Color whose RGBA component values are a weighted sum of this color and other. Each component of the returned color is the fraction of other's value plus 1 - fraction of this color's.

Availability:
Available in MochiKit 1.3.1+

Color.prototype.isLight():

Return true if the lightness value of this color is greater than 0.5.

Note that alpha is ignored for this calculation (color components are not premultiplied).

Availability:
Available in MochiKit 1.3.1+

Color.prototype.isDark():

Return true if the lightness value of this color is less than or equal to 0.5.

Note that alpha is ignored for this calculation (color components are not premultiplied).

Availability:
Available in MochiKit 1.3.1+

Color.prototype.toRGBString():

Return the decimal "rgb(red, green, blue)" string representation of this color.

If the alpha component is not 1.0 (fully opaque), the "rgba(red, green, blue, alpha)" string representation will be used.

For example:

assert( Color.whiteColor().toRGBString() == "rgb(255,255,255)" );
Availability:
Available in MochiKit 1.3.1+

Color.prototype.toHSLString():

Return the decimal "hsl(hue, saturation, lightness)" string representation of this color.

If the alpha component is not 1.0 (fully opaque), the "hsla(hue, saturation, lightness, alpha)" string representation will be used.

For example:

assert( Color.whiteColor().toHSLString() == "hsl(0,0,360)" );
Availability:
Available in MochiKit 1.3.1+

Color.prototype.toHexString():

Return the hexadecimal "#RRGGBB" string representation of this color.

Note that the alpha component is completely ignored for hexadecimal string representations!

For example:

assert( Color.whiteColor().toHexString() == "#FFFFFF" );
Availability:
Available in MochiKit 1.3.1+

Color.prototype.asRGB():

Return the RGB (red, green, blue, alpha) components of this color as an object with r, g, b, and a properties that have values between 0.0 and 1.0.

Availability:
Available in MochiKit 1.3.1+

Color.prototype.asHSL():

Return the HSL (hue, saturation, lightness, alpha) components of this color as an object with h, s, l and a properties that have values between 0.0 and 1.0.

Availability:
Available in MochiKit 1.3.1+

Color.prototype.asHSV():

Return the HSV (hue, saturation, value, alpha) components of this color as an object with h, s, v and a properties that have values between 0.0 and 1.0.

Availability:
Available in MochiKit 1.3.1+

Color.blackColor():

Return a Color object whose RGB values are 0, 0, 0 (#000000).

Availability:
Available in MochiKit 1.3.1+

Color.blueColor():

Return a Color object whose RGB values are 0, 0, 1 (#0000ff).

Availability:
Available in MochiKit 1.3.1+

Color.brownColor():

Return a Color object whose RGB values are 0.6, 0.4, 0.2 (#996633).

Availability:
Available in MochiKit 1.3.1+

Color.cyanColor():

Return a Color object whose RGB values are 0, 1, 1 (#00ffff).

Availability:
Available in MochiKit 1.3.1+

Color.darkGrayColor():

Return a Color object whose RGB values are 1/3, 1/3, 1/3 (#555555).

Availability:
Available in MochiKit 1.3.1+

Color.grayColor():

Return a Color object whose RGB values are 0.5, 0.5, 0.5 (#808080).

Availability:
Available in MochiKit 1.3.1+

Color.greenColor():

Return a Color object whose RGB values are 0, 1, 0. (#00ff00).

Availability:
Available in MochiKit 1.3.1+

Color.lightGrayColor():

Return a Color object whose RGB values are 2/3, 2/3, 2/3 (#aaaaaa).

Availability:
Available in MochiKit 1.3.1+

Color.magentaColor():

Return a Color object whose RGB values are 1, 0, 1 (#ff00ff).

Availability:
Available in MochiKit 1.3.1+

Color.orangeColor():

Return a Color object whose RGB values are 1, 0.5, 0 (#ff8000).

Availability:
Available in MochiKit 1.3.1+

Color.purpleColor():

Return a Color object whose RGB values are 0.5, 0, 0.5 (#800080).

Availability:
Available in MochiKit 1.3.1+

Color.redColor():

Return a Color object whose RGB values are 1, 0, 0 (#ff0000).

Availability:
Available in MochiKit 1.3.1+

Color.whiteColor():

Return a Color object whose RGB values are 1, 1, 1 (#ffffff).

Availability:
Available in MochiKit 1.3.1+

Color.yellowColor():

Return a Color object whose RGB values are 1, 1, 0 (#ffff00).

Availability:
Available in MochiKit 1.3.1+

Color.transparentColor():

Return a Color object that is completely transparent (has alpha component of 0).

Availability:
Available in MochiKit 1.3.1+

Functions

clampColorComponent(num, scale):

Returns num * scale clamped between 0 and scale.

clampColorComponent is not exported by default when using JSAN.

Availability:
Available in MochiKit 1.3.1+

hslToRGB(hue, saturation, lightness, alpha):

Computes RGB values from the provided HSL values. The return value is a mapping with "r", "g", "b" and "a" keys.

Alternate form:
hslToRGB({h: hue, s: saturation, l: lightness, a: alpha}).

hslToRGB is not exported by default when using JSAN.

Availability:
Available in MochiKit 1.3.1+

hsvToRGB(hue, saturation, value, alpha):

Computes RGB values from the provided HSV values. The return value is a mapping with "r", "g", "b" and "a" keys.

Alternate form:
hsvToRGB({h: hue, s: saturation, v: value, a: alpha}).

hsvToRGB is not exported by default when using JSAN.

Availability:
Available in MochiKit 1.3.1+

toColorPart(num):

Convert num to a zero padded hexadecimal digit for use in a hexadecimal color string. Num should be an integer between 0 and 255.

toColorPart is not exported by default when using JSAN.

Availability:
Available in MochiKit 1.3.1+

rgbToHSL(red, green, blue, alpha):

Computes HSL values based on the provided RGB values. The return value is a mapping with "h", "s", "l" and "a" keys.

Alternate form:
rgbToHSL({r: red, g: green, b: blue, a: alpha}).

rgbToHSL is not exported by default when using JSAN.

Availability:
Available in MochiKit 1.3.1+

rgbToHSV(red, green, blue, alpha):

Computes HSV values based on the provided RGB values. The return value is a mapping with "h", "s", "v" and "a" keys.

Alternate form:
rgbToHSV({r: red, g: green, b: blue, a: alpha}).

rgbToHSV is not exported by default when using JSAN.

Availability:
Available in MochiKit 1.3.1+

Authors

Copyright

Copyright 2005 Bob Ippolito <bob@redivi.com>. This program is dual-licensed free software; you can redistribute it and/or modify it under the terms of the MIT License or the Academic Free License v2.1.

MochiKit-1.4.2/Changes0000660000175000017500000004461011113645622013576 0ustar scottscott2008-11-27 v1.4.2 (bug fix release) - Changed default packed version to contain all modules (since easy customization is now available). - More fixes in MochiKit.Style.getElementDimensions for IE and hidden elements (#325). - Fixed issue in MochiKit.Style.getViewportDimensions when called within the document HEAD. - Fixed MochiKit.DOM.coerceToDOM() handling of arrays when MochiKit.Iter is not loaded (#328). 2008-11-02 v1.4.1 (bug fix release) - Added export of deprecated MochiKit.DOM.computedStyle function (#324). - Fixed issue in MochiKit.Style.getElementDimensions when elements are hidden due to CSS class definitions (#325). - Moved makePositioned, undoPositioned, makeClipping and undoClipping from MochiKit.DOM to MochiKit.Style due to circular dependency (#327). - Fixed makeClipping and undoClipping to handle overflow-x and overflow-y styles correctly (#326). - Fixed issue with Event.relatedTarget() sometimes returning XUL elements in Mozilla-based browsers (#322). 2008-10-21 v1.4 - Added pt_BR to MochiKit.Format.LOCALE. - MochiKit.Async now sets the "X-Requested-With: XMLHttpRequest" header, a de facto standard (Prototype, jQuery, Mootools). - MochiKit.Signal custom handlers no longer cause callbacks to get re-bound to the source if they were previously bound. - Fixed MochiKit.Signal.signal re-entrancy bug that could cause recently disconnected slots to get signaled. - MochiKit.Base.evalJSON will now evaluate JSON that is wrapped in a ``/* comment block */``. - MochiKit.Color's HSV to RGB conversion code fixed to return the correct value (hsv.v for RGB values) in cases where saturation === 0. - doXHR workaround for a Mozilla bug when calling XMLHttpRequest in certain situations. Always wraps call in a callLater(0, doXHR, url, opts). - parseQueryString will now parse values with embedded "=" - Workaround for a Safari DOM crash when using MochiKit.Iter.list. http://bugs.webkit.org/show_bug.cgi?id=12191 - New removeNodeAttribute function in MochiKit.DOM. - MochiKit.Async.doXHR and dependent functions now accept 201 CREATED and 204 NO CONTENT as valid. - MochiKit.DOM.formContents now treats option tags the same way that form posts do in the case of missing and empty string value attributes, even in IE. - MochiKit.Base.queryString now accepts third queryString([names, values]) form. - MochiKit.DOM.formContents now defaults to document.body if no element is given. - New MochiKit.Selector module (still somewhat experimental) - MochiKit.LoggingPane fixes for Internet Explorer - MochiKit.DOM now creates XHTML nodes in XUL documents. - MochiKit.LoggingPane now works on pages with '#' in the URL on IE - New MochiKit.Async.doXHR as a convenient method for doing custom XMLHttpRequests (e.g. extra headers, overrideMimeType, etc.) - New __connect__ protocol for MochiKit.Signal.connect source notifications - Added colSpan, bgColor to the list of DOM renames for Internet Explorer - New MochiKit.Signal.disconnectAllTo function - MochiKit.Base.parseQueryString now accepts leading question mark - New MochiKit.Base.values function - Fixed MochiKit.Signal.disconnect when called from a signal handler invoked by MochiKit.Signal.signal - parseQueryString now splits on HTML entities equivalent to ampersand as well - Better XHTML compatibility (removed obvious cases where uppercase tagName or nodeName was assumed) - MochiKit.Base.queryString now handles array values in the same way HTML forms handle multiple elements of the same name. - MochiKit.Base.parseQueryString now returns {} for empty query string instead of {"": "undefined"} - MochiKit.DOM.formContents now handles option value="" correctly. - MochiKit.DOM now checks for undefined className. - MochiKit.Iter.groupby() now uses compare() to group rather than == and != - serializeJSON no longer serializes undefined, as per the JSON spec - Fixed an infinite recursion bug in serializeJSON if an adapter returns the object itself. - Fixed vertical tab and control char encoding in serializeJSON (#313). - New MochiKit.Base.operator.seq and sne to support strict comparison - MochiKit.Base.isArrayLike no longer returns true for DOM text nodes - Added readonly-readOnly to the list of DOM renames for Internet Explorer - New MochiKit.Signal event method: confirmUnload (sets returnValue for onbeforeunload) - Fix interpreter help() function for Firefox and IE - API version compatibility notes added - New MochiKit.Base functions methodcaller and compose - Support IE-based native console logging (Debugger, Atlas) - Refactored style functions from MochiKit.DOM to MochiKit.Style - MochiKit.Async.DeferredList is now a proper Deferred - MochiKit.DOM.formContents now supports SELECT multiple tags - Re-use StopIteration Error if the browser already has it - Workaround IE type="" bug for INPUT elements - Allow LoggingPane to work in IE with hyphen-containing URLs - Replace percents for Safari native logging to avoid crashing - New MochiKit.DOM.coerceToDOM .dom(node) / .__dom__(node) protocol - MochiKit.DOM's MochiKit.Iter dependency is now optional - Added expand all link to the documentation index - Added MochiKit.DOM.isChildNode function. - Added synthesizing for onmouseenter/onmouseleave - Added animation functions and classes to MochiKit.Visual. - Added MochiKit.Style.getElementDimensions support for calculating the actual content size (without padding and borders). - Added MochiKit.DOM.insertSiblingNodesBefore, getFirstElementByTagAndClassName, getFirstParentByTagAndClassName, makeClipping, makePositioned, undoClipping, undoPositioned and removeEmptyTextNodes functions. - Added MochiKit.Base.bindLate, camelize, flattenArray, mean, median and noop functions. - New MochiKit.DragAndDrop module for drag and drop handling. - New MochiKit.Sortable module for lists sortable with drag and drop. - Changed MochiKit.Signal.connect to use late function binding also for non-DOM signals (#307). - Fixed MochiKit.Color.isColor when symbols not exported (#296). - Added support for inclusion in SVG files (#290). - Fixed rounding errors in MochiKit.Format.twoDigitFloat (#275). - Fixed MochiKit.Logging to convert log levels to strings (#273). - Fixed MochiKit.Iter.forEach and iextend for array-like objects with and iter function (#268). 2006-04-29 v1.3.1 (bug fix release) - Fix sendXMLHttpRequest sendContent regression - Internet Explorer fix in MochiKit.Logging (printfire exception) - Internet Explorer XMLHttpRequest object leak fixed in MochiKit.Async 2006-04-26 v1.3 "warp zone" - IMPORTANT: Renamed MochiKit.Base.forward to forwardCall (for export) - IMPORTANT: Renamed MochiKit.Base.find to findValue (for export) - New MochiKit.Base.method as a convenience form of bind that takes the object before the method - New MochiKit.Base.flattenArguments for flattening a list of arguments to a single Array - Refactored MochiRegExp example to use MochiKit.Signal - New key_events example demonstrating use of MochiKit.Signal's key handling capabilities. - MochiKit.DOM.createDOM API change for convenience: if attrs is a string, null is used and the string will be considered the first node. This allows for the more natural P("foo") rather than P(null, "foo"). - MochiKit Interpreter example refactored to use MochiKit.Signal and now provides multi-line input and a help() function to get MochiKit function signature from the documentation. - Native Console Logging for the default MochiKit.Logging logger - New MochiKit.Async.DeferredList, gatherResults, maybeDeferred - New MochiKit.Signal example: draggable - Added sanity checking to Deferred to ensure that errors happen when chaining is used incorrectly - Opera sendXMLHttpRequest fix (sends empty string instead of null by default) - Fix a bug in MochiKit.Color that incorrectly generated hex colors for component values smaller than 16/255. - Fix a bug in MochiKit.Logging that prevented logs from being capped at a maximum size - MochiKit.Async.Deferred will now wrap thrown objects that are not instanceof Error, so that the errback chain is used instead of the callback chain. - MochiKit.DOM.appendChildNodes and associated functions now append iterables in the correct order. - New MochiKit-based SimpleTest test runner as a replacement for Test.Simple - MochiKit.Base.isNull no longer matches undefined - example doctypes changed to HTML4 - isDateLike no longer throws error on null - New MochiKit.Signal module, modeled after the slot/signal mechanism in Qt - updated elementDimensions to calculate width from offsetWidth instead of clientWidth - formContents now works with FORM tags that have a name attribute - Documentation now uses MochiKit to generate a function index 2006-01-26 v1.2 "the ocho" - Fixed MochiKit.Color.Color.lighterColorWithLevel - Added new MochiKit.Base.findIdentical function to find the index of an element in an Array-like object. Uses === for identity comparison. - Added new MochiKit.Base.find function to find the index of an element in an Array-like object. Uses compare for rich comparison. - MochiKit.Base.bind will accept a string for func, which will be immediately looked up as self[func]. - MochiKit.DOM.formContents no longer skips empty form elements for Zope compatibility - MochiKit.Iter.forEach will now catch StopIteration to break - New MochiKit.DOM.elementDimensions(element) for determining the width and height of an element in the document - MochiKit.DOM's initialization is now compatible with HTMLUnit + JWebUnit + Rhino - MochiKit.LoggingPane will now re-use a ``_MochiKit_LoggingPane`` DIV element currently in the document instead of always creating one. - MochiKit.Base now has operator.mul - MochiKit.DOM.formContents correctly handles unchecked checkboxes that have a custom value attribute - Added new MochiKit.Color constructors fromComputedStyle and fromText - MochiKit.DOM.setNodeAttribute should work now - MochiKit.DOM now has a workaround for an IE bug when setting the style property to a string - MochiKit.DOM.createDOM now has workarounds for IE bugs when setting the name and for properties - MochiKit.DOM.scrapeText now walks the DOM tree in-order - MochiKit.LoggingPane now sanitizes the window name to work around IE bug - MochiKit.DOM now translates usemap to useMap to work around IE bug - MochiKit.Logging is now resistant to Prototype's dumb Object.prototype hacks - Added new MochiKit.DOM documentation on element visibility - New MochiKit.DOM.elementPosition(element[, relativeTo={x: 0, y: 0}]) for determining the position of an element in the document - Added new MochiKit.DOM createDOMFunc aliases: CANVAS, STRONG 2005-11-14 v1.1 - Fixed a bug in numberFormatter with large numbers - Massively overhauled documentation - Fast-path for primitives in MochiKit.Base.compare - New groupby and groupby_as_array in MochiKit.Iter - Added iterator factory adapter for objects that implement iterateNext() - Fixed isoTimestamp to handle timestamps with time zone correctly - Added new MochiKit.DOM createDOMFunc aliases: SELECT, OPTION, OPTGROUP, LEGEND, FIELDSET - New MochiKit.DOM formContents and enhancement to queryString to support it - Updated view_source example to use dp.SyntaxHighlighter 1.3.0 - MochiKit.LoggingPane now uses named windows based on the URL so that a given URL will get the same LoggingPane window after a reload (at the same position, etc.) - MochiKit.DOM now has currentWindow() and currentDocument() context variables that are set with withWindow() and withDocument(). These context variables affect all MochiKit.DOM functionality (getElement, createDOM, etc.) - MochiKit.Base.items will now catch and ignore exceptions for properties that are enumerable but not accessible (e.g. permission denied) - MochiKit.Async.Deferred's addCallback/addErrback/addBoth now accept additional arguments that are used to create a partially applied function. This differs from Twisted in that the callback/errback result becomes the *last* argument, not the first when this feature is used. - MochiKit.Async's doSimpleXMLHttpRequest will now accept additional arguments which are used to create a GET query string - Did some refactoring to reduce the footprint of MochiKit by a few kilobytes - escapeHTML to longer escapes ' (apos) and now uses String.replace instead of iterating over every char. - Added DeferredLock to Async - Renamed getElementsComputedStyle to computedStyle and moved it from MochiKit.Visual to MochiKit.DOM - Moved all color support out of MochiKit.Visual and into MochiKit.Color - Fixed range() to accept a negative step - New alias to MochiKit.swapDOM called removeElement - New MochiKit.DOM.setNodeAttribute(node, attr, value) which sets an attribute on a node without raising, roughly equivalent to: updateNodeAttributes(node, {attr: value}) - New MochiKit.DOM.getNodeAttribute(node, attr) which gets the value of a node's attribute or returns null without raising - Fixed a potential IE memory leak if using MochiKit.DOM.addToCallStack directly (addLoadEvent did not leak, since it clears the handler) 2005-10-24 v1.0 - New interpreter example that shows usage of MochiKit.DOM to make an interactive JavaScript interpreter - New MochiKit.LoggingPane for use with the MochiKit.Logging debuggingBookmarklet, with logging_pane example to show its usage - New mochiregexp example that demonstrates MochiKit.DOM and MochiKit.Async in order to provide a live regular expression matching tool - Added advanced number formatting capabilities to MochiKit.Format: numberFormatter(pattern, placeholder="", locale="default") and formatLocale(locale="default") - Added updatetree(self, obj[, ...]) to MochiKit.Base, and changed MochiKit.DOM's updateNodeAttributes(node, attrs) to use it when appropiate. - Added new MochiKit.DOM createDOMFunc aliases: BUTTON, TT, PRE - Added truncToFixed(aNumber, precision) and roundToFixed(aNumber, precision) to MochiKit.Format - MochiKit.DateTime can now handle full ISO 8601 timestamps, specifically isoTimestamp(isoString) will convert them to Date objects, and toISOTimestamp(date, true) will return an ISO 8601 timestamp in UTC - Fixed missing errback for sendXMLHttpRequest when the server does not respond - Fixed infinite recusion bug when using roundClass("DIV", ...) - Fixed a bug in MochiKit.Async wait (and callLater) that prevented them from being cancelled properly - Workaround in MochiKit.Base bind (and partial) for functions that don't have an apply method, such as alert - Reliably return null from the string parsing/manipulation functions if the input can't be coerced to a string (s + "") or the input makes no sense; e.g. isoTimestamp(null) and isoTimestamp("") return null 2005-10-08 v0.90 - Fixed ISO compliance with toISODate - Added missing operator.sub - Placated Mozilla's strict warnings a bit - Added JSON serialization and unserialization support to MochiKit.Base: serializeJSON, evalJSON, registerJSON. This is very similar to the repr API. - Fixed a bug in the script loader that failed in some scenarios when a script tag did not have a "src" attribute (thanks Ian!) - Added new MochiKit.DOM createDOMFunc aliases: H1, H2, H3, BR, HR, TEXTAREA, P, FORM - Use encodeURIComponent / decodeURIComponent for MochiKit.Base urlEncode and parseQueryString, when available. 2005-08-12 v0.80 - Source highlighting in all examples, moved to a view-source example - Added some experimental syntax highlighting for the Rounded Corners example, via the LGPL dp.SyntaxHighlighter 1.2.0 now included in examples/common/lib - Use an indirect binding for the logger conveniences, so that the global logger could be replaced by setting MochiKit.Logger.logger to something else (though an observer is probably a better choice). - Allow MochiKit.DOM.getElementsByTagAndClassName to take a string for parent, which will be looked up with getElement - Fixed bug in MochiKit.Color.fromBackground (was using node.parent instead of node.parentNode) - Consider a 304 (NOT_MODIFIED) response from XMLHttpRequest to be success - Disabled Mozilla map(...) fast-path due to Deer Park compatibility issues - Possible workaround for Safari issue with swapDOM, where it would get confused because two elements were in the DOM at the same time with the same id - Added missing THEAD convenience function to MochiKit.DOM - Added lstrip, rstrip, strip to MochiKit.Format - Added updateNodeAttributes, appendChildNodes, replaceChildNodes to MochiKit.DOM - MochiKit.Iter.iextend now has a fast-path for array-like objects - Added HSV color space support to MochiKit.Visual - Fixed a bug in the sortable_tables example, it now converts types correctly - Fixed a bug where MochiKit.DOM referenced MochiKit.Iter.next from global scope 2005-08-04 v0.70 - New ajax_tables example, which shows off XMLHttpRequest, ajax, json, and a little TAL-ish DOM templating attribute language. - sendXMLHttpRequest and functions that use it (loadJSONDoc, etc.) no longer ignore requests with status == 0, which seems to happen for cached or local requests - Added sendXMLHttpRequest to MochiKit.Async.EXPORT, d'oh. - Changed scrapeText API to return a string by default. This is API-breaking! It was dumb to have the default return value be the form you almost never want. Sorry. - Added special form to swapDOM(dest, src). If src is null, dest is removed (where previously you'd likely get a DOM exception). - Added three new functions to MochiKit.Base for dealing with URL query strings: urlEncode, queryString, parseQueryString - MochiKit.DOM.createDOM will now use attr[k] = v for all browsers if the name starts with "on" (e.g. "onclick"). If v is a string, it will set it to new Function(v). - Another workaround for Internet "worst browser ever" Explorer's setAttribute usage in MochiKit.DOM.createDOM (checked -> defaultChecked). - Added UL, OL, LI convenience createDOM aliases to MochiKit.DOM - Packing is now done by Dojo's custom Rhino interpreter, so it's much smaller now! 2005-07-29 v0.60 - Beefed up the MochiKit.DOM test suite - Fixed return value for MochiKit.DOM.swapElementClass, could return false unexpectedly before - Added an optional "parent" argument to MochiKit.DOM.getElementsByTagAndClassName - Added a "packed" version in packed/MochiKit/MochiKit.js - Changed build script to rewrite the URLs in tests to account for the JSAN-required reorganization - MochiKit.Compat to potentially work around IE 5.5 issues (5.0 still not supported). Test.Simple doesn't seem to work there, though. - Several minor documentation corrections 2005-07-27 v0.50 - Initial Release MochiKit-1.4.2/packed/0000755000175000017500000000000011136470265013533 5ustar scottscottMochiKit-1.4.2/packed/MochiKit/0000755000175000017500000000000011136470265015242 5ustar scottscottMochiKit-1.4.2/packed/MochiKit/__package__.js0000660000175000017500000000015311102215574017755 0ustar scottscottdojo.kwCompoundRequire({ "common": [ "MochiKit.MochiKit" ] }); dojo.provide("MochiKit.*"); MochiKit-1.4.2/packed/MochiKit/customize.html0000660000175000017500000001740711113647642020161 0ustar scottscott MochiKit Customizer I ♥ MochiKit

MochiKit Customizer

Module Sets:


Additional Options:


MochiKit-1.4.2/packed/MochiKit/MochiKit.js0000660000175000017500000061302611113647640017313 0ustar scottscott/*** MochiKit.MochiKit 1.4.2 : PACKED VERSION THIS FILE IS AUTOMATICALLY GENERATED. If creating patches, please diff against the source tree, not this file. See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.Base"); } if(typeof (MochiKit)=="undefined"){ MochiKit={}; } if(typeof (MochiKit.Base)=="undefined"){ MochiKit.Base={}; } if(typeof (MochiKit.__export__)=="undefined"){ MochiKit.__export__=(MochiKit.__compat__||(typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")); } MochiKit.Base.VERSION="1.4.2"; MochiKit.Base.NAME="MochiKit.Base"; MochiKit.Base.update=function(_1,_2){ if(_1===null||_1===undefined){ _1={}; } for(var i=1;i=0;i--){ _18.unshift(o[i]); } }else{ res.push(o); } } return res; },extend:function(_1b,obj,_1d){ if(!_1d){ _1d=0; } if(obj){ var l=obj.length; if(typeof (l)!="number"){ if(typeof (MochiKit.Iter)!="undefined"){ obj=MochiKit.Iter.list(obj); l=obj.length; }else{ throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); } } if(!_1b){ _1b=[]; } for(var i=_1d;i>b; },zrshift:function(a,b){ return a>>>b; },eq:function(a,b){ return a==b; },ne:function(a,b){ return a!=b; },gt:function(a,b){ return a>b; },ge:function(a,b){ return a>=b; },lt:function(a,b){ return al){ _93=l; } } _91=[]; for(i=0;i<_93;i++){ var _95=[]; for(var j=1;j=0;i--){ _b2=[_ae[i].apply(this,_b2)]; } return _b2[0]; }; },bind:function(_b4,_b5){ if(typeof (_b4)=="string"){ _b4=_b5[_b4]; } var _b6=_b4.im_func; var _b7=_b4.im_preargs; var _b8=_b4.im_self; var m=MochiKit.Base; if(typeof (_b4)=="function"&&typeof (_b4.apply)=="undefined"){ _b4=m._wrapDumbFunction(_b4); } if(typeof (_b6)!="function"){ _b6=_b4; } if(typeof (_b5)!="undefined"){ _b8=_b5; } if(typeof (_b7)=="undefined"){ _b7=[]; }else{ _b7=_b7.slice(); } m.extend(_b7,arguments,2); var _ba=function(){ var _bb=arguments; var me=arguments.callee; if(me.im_preargs.length>0){ _bb=m.concat(me.im_preargs,_bb); } var _bd=me.im_self; if(!_bd){ _bd=this; } return me.im_func.apply(_bd,_bb); }; _ba.im_self=_b8; _ba.im_func=_b6; _ba.im_preargs=_b7; return _ba; },bindLate:function(_be,_bf){ var m=MochiKit.Base; if(typeof (_be)!="string"){ return m.bind.apply(this,arguments); } var _c1=m.extend([],arguments,2); var _c2=function(){ var _c3=arguments; var me=arguments.callee; if(me.im_preargs.length>0){ _c3=m.concat(me.im_preargs,_c3); } var _c5=me.im_self; if(!_c5){ _c5=this; } return _c5[me.im_func].apply(_c5,_c3); }; _c2.im_self=_bf; _c2.im_func=_be; _c2.im_preargs=_c1; return _c2; },bindMethods:function(_c6){ var _c7=MochiKit.Base.bind; for(var k in _c6){ var _c9=_c6[k]; if(typeof (_c9)=="function"){ _c6[k]=_c7(_c9,_c6); } } },registerComparator:function(_ca,_cb,_cc,_cd){ MochiKit.Base.comparatorRegistry.register(_ca,_cb,_cc,_cd); },_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){ if(a==b){ return 0; } var _d0=(typeof (a)=="undefined"||a===null); var _d1=(typeof (b)=="undefined"||b===null); if(_d0&&_d1){ return 0; }else{ if(_d0){ return -1; }else{ if(_d1){ return 1; } } } var m=MochiKit.Base; var _d3=m._primitives; if(!(typeof (a) in _d3&&typeof (b) in _d3)){ try{ return m.comparatorRegistry.match(a,b); } catch(e){ if(e!=m.NotFound){ throw e; } } } if(ab){ return 1; } } var _d4=m.repr; throw new TypeError(_d4(a)+" and "+_d4(b)+" can not be compared"); },compareDateLike:function(a,b){ return MochiKit.Base.compare(a.getTime(),b.getTime()); },compareArrayLike:function(a,b){ var _d9=MochiKit.Base.compare; var _da=a.length; var _db=0; if(_da>b.length){ _db=1; _da=b.length; }else{ if(_da=0;i--){ sum+=o[i]; } }else{ sum+=o; } } if(_121<=0){ throw new TypeError("mean() requires at least one argument"); } return sum/_121; },median:function(){ var data=MochiKit.Base.flattenArguments(arguments); if(data.length===0){ throw new TypeError("median() requires at least one argument"); } data.sort(compare); if(data.length%2==0){ var _125=data.length/2; return (data[_125]+data[_125-1])/2; }else{ return data[(data.length-1)/2]; } },findValue:function(lst,_127,_128,end){ if(typeof (end)=="undefined"||end===null){ end=lst.length; } if(typeof (_128)=="undefined"||_128===null){ _128=0; } var cmp=MochiKit.Base.compare; for(var i=_128;i0))){ var kv=MochiKit.DOM.formContents(_135); _135=kv[0]; _136=kv[1]; }else{ if(arguments.length==1){ if(typeof (_135.length)=="number"&&_135.length==2){ return arguments.callee(_135[0],_135[1]); } var o=_135; _135=[]; _136=[]; for(var k in o){ var v=o[k]; if(typeof (v)=="function"){ continue; }else{ if(MochiKit.Base.isArrayLike(v)){ for(var i=0;i=stop){ throw self.StopIteration; } _183+=step; return rval; }}; },imap:function(fun,p,q){ var m=MochiKit.Base; var self=MochiKit.Iter; var _18d=m.map(self.iter,m.extend(null,arguments,1)); var map=m.map; var next=self.next; return {repr:function(){ return "imap(...)"; },toString:m.forwardCall("repr"),next:function(){ return fun.apply(this,map(next,_18d)); }}; },applymap:function(fun,seq,self){ seq=MochiKit.Iter.iter(seq); var m=MochiKit.Base; return {repr:function(){ return "applymap(...)"; },toString:m.forwardCall("repr"),next:function(){ return fun.apply(self,seq.next()); }}; },chain:function(p,q){ var self=MochiKit.Iter; var m=MochiKit.Base; if(arguments.length==1){ return self.iter(arguments[0]); } var _198=m.map(self.iter,arguments); return {repr:function(){ return "chain(...)"; },toString:m.forwardCall("repr"),next:function(){ while(_198.length>1){ try{ var _199=_198[0].next(); return _199; } catch(e){ if(e!=self.StopIteration){ throw e; } _198.shift(); var _199=_198[0].next(); return _199; } } if(_198.length==1){ var arg=_198.shift(); this.next=m.bind("next",arg); return this.next(); } throw self.StopIteration; }}; },takewhile:function(pred,seq){ var self=MochiKit.Iter; seq=self.iter(seq); return {repr:function(){ return "takewhile(...)"; },toString:MochiKit.Base.forwardCall("repr"),next:function(){ var rval=seq.next(); if(!pred(rval)){ this.next=function(){ throw self.StopIteration; }; this.next(); } return rval; }}; },dropwhile:function(pred,seq){ seq=MochiKit.Iter.iter(seq); var m=MochiKit.Base; var bind=m.bind; return {"repr":function(){ return "dropwhile(...)"; },"toString":m.forwardCall("repr"),"next":function(){ while(true){ var rval=seq.next(); if(!pred(rval)){ break; } } this.next=bind("next",seq); return rval; }}; },_tee:function(_1a4,sync,_1a6){ sync.pos[_1a4]=-1; var m=MochiKit.Base; var _1a8=m.listMin; return {repr:function(){ return "tee("+_1a4+", ...)"; },toString:m.forwardCall("repr"),next:function(){ var rval; var i=sync.pos[_1a4]; if(i==sync.max){ rval=_1a6.next(); sync.deque.push(rval); sync.max+=1; sync.pos[_1a4]+=1; }else{ rval=sync.deque[i-sync.min]; sync.pos[_1a4]+=1; if(i==sync.min&&_1a8(sync.pos)!=sync.min){ sync.min+=1; sync.deque.shift(); } } return rval; }}; },tee:function(_1ab,n){ var rval=[]; var sync={"pos":[],"deque":[],"max":-1,"min":-1}; if(arguments.length==1||typeof (n)=="undefined"||n===null){ n=2; } var self=MochiKit.Iter; _1ab=self.iter(_1ab); var _tee=self._tee; for(var i=0;i0&&_1bd>=stop)||(step<0&&_1bd<=stop)){ throw MochiKit.Iter.StopIteration; } var rval=_1bd; _1bd+=step; return rval; },repr:function(){ return "range("+[_1bd,stop,step].join(", ")+")"; },toString:MochiKit.Base.forwardCall("repr")}; },sum:function(_1c1,_1c2){ if(typeof (_1c2)=="undefined"||_1c2===null){ _1c2=0; } var x=_1c2; var self=MochiKit.Iter; _1c1=self.iter(_1c1); try{ while(true){ x+=_1c1.next(); } } catch(e){ if(e!=self.StopIteration){ throw e; } } return x; },exhaust:function(_1c5){ var self=MochiKit.Iter; _1c5=self.iter(_1c5); try{ while(true){ _1c5.next(); } } catch(e){ if(e!=self.StopIteration){ throw e; } } },forEach:function(_1c7,func,obj){ var m=MochiKit.Base; var self=MochiKit.Iter; if(arguments.length>2){ func=m.bind(func,obj); } if(m.isArrayLike(_1c7)&&!self.isIterable(_1c7)){ try{ for(var i=0;i<_1c7.length;i++){ func(_1c7[i]); } } catch(e){ if(e!=self.StopIteration){ throw e; } } }else{ self.exhaust(self.imap(func,_1c7)); } },every:function(_1cd,func){ var self=MochiKit.Iter; try{ self.ifilterfalse(func,_1cd).next(); return false; } catch(e){ if(e!=self.StopIteration){ throw e; } return true; } },sorted:function(_1d0,cmp){ var rval=MochiKit.Iter.list(_1d0); if(arguments.length==1){ cmp=MochiKit.Base.compare; } rval.sort(cmp); return rval; },reversed:function(_1d3){ var rval=MochiKit.Iter.list(_1d3); rval.reverse(); return rval; },some:function(_1d5,func){ var self=MochiKit.Iter; try{ self.ifilter(func,_1d5).next(); return true; } catch(e){ if(e!=self.StopIteration){ throw e; } return false; } },iextend:function(lst,_1d9){ var m=MochiKit.Base; var self=MochiKit.Iter; if(m.isArrayLike(_1d9)&&!self.isIterable(_1d9)){ for(var i=0;i<_1d9.length;i++){ lst.push(_1d9[i]); } }else{ _1d9=self.iter(_1d9); try{ while(true){ lst.push(_1d9.next()); } } catch(e){ if(e!=self.StopIteration){ throw e; } } } return lst; },groupby:function(_1dd,_1de){ var m=MochiKit.Base; var self=MochiKit.Iter; if(arguments.length<2){ _1de=m.operator.identity; } _1dd=self.iter(_1dd); var pk=undefined; var k=undefined; var v; function fetch(){ v=_1dd.next(); k=_1de(v); } function eat(){ var ret=v; v=undefined; return ret; } var _1e5=true; var _1e6=m.compare; return {repr:function(){ return "groupby(...)"; },next:function(){ while(_1e6(k,pk)===0){ fetch(); if(_1e5){ _1e5=false; break; } } pk=k; return [k,{next:function(){ if(v==undefined){ fetch(); } if(_1e6(k,pk)!==0){ throw self.StopIteration; } return eat(); }}]; }}; },groupby_as_array:function(_1e7,_1e8){ var m=MochiKit.Base; var self=MochiKit.Iter; if(arguments.length<2){ _1e8=m.operator.identity; } _1e7=self.iter(_1e7); var _1eb=[]; var _1ec=true; var _1ed; var _1ee=m.compare; while(true){ try{ var _1ef=_1e7.next(); var key=_1e8(_1ef); } catch(e){ if(e==self.StopIteration){ break; } throw e; } if(_1ec||_1ee(key,_1ed)!==0){ var _1f1=[]; _1eb.push([key,_1f1]); } _1f1.push(_1ef); _1ec=false; _1ed=key; } return _1eb; },arrayLikeIter:function(_1f2){ var i=0; return {repr:function(){ return "arrayLikeIter(...)"; },toString:MochiKit.Base.forwardCall("repr"),next:function(){ if(i>=_1f2.length){ throw MochiKit.Iter.StopIteration; } return _1f2[i++]; }}; },hasIterateNext:function(_1f4){ return (_1f4&&typeof (_1f4.iterateNext)=="function"); },iterateNextIter:function(_1f5){ return {repr:function(){ return "iterateNextIter(...)"; },toString:MochiKit.Base.forwardCall("repr"),next:function(){ var rval=_1f5.iterateNext(); if(rval===null||rval===undefined){ throw MochiKit.Iter.StopIteration; } return rval; }}; }}); MochiKit.Iter.EXPORT_OK=["iteratorRegistry","arrayLikeIter","hasIterateNext","iterateNextIter"]; MochiKit.Iter.EXPORT=["StopIteration","registerIteratorFactory","iter","count","cycle","repeat","next","izip","ifilter","ifilterfalse","islice","imap","applymap","chain","takewhile","dropwhile","tee","list","reduce","range","sum","exhaust","forEach","every","sorted","reversed","some","iextend","groupby","groupby_as_array"]; MochiKit.Iter.__new__=function(){ var m=MochiKit.Base; if(typeof (StopIteration)!="undefined"){ this.StopIteration=StopIteration; }else{ this.StopIteration=new m.NamedError("StopIteration"); } this.iteratorRegistry=new m.AdapterRegistry(); this.registerIteratorFactory("arrayLike",m.isArrayLike,this.arrayLikeIter); this.registerIteratorFactory("iterateNext",this.hasIterateNext,this.iterateNextIter); this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }; MochiKit.Iter.__new__(); if(MochiKit.__export__){ reduce=MochiKit.Iter.reduce; } MochiKit.Base._exportSymbols(this,MochiKit.Iter); MochiKit.Base._deps("Logging",["Base"]); MochiKit.Logging.NAME="MochiKit.Logging"; MochiKit.Logging.VERSION="1.4.2"; MochiKit.Logging.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Logging.toString=function(){ return this.__repr__(); }; MochiKit.Logging.EXPORT=["LogLevel","LogMessage","Logger","alertListener","logger","log","logError","logDebug","logFatal","logWarning"]; MochiKit.Logging.EXPORT_OK=["logLevelAtLeast","isLogMessage","compareLogMessage"]; MochiKit.Logging.LogMessage=function(num,_1f9,info){ this.num=num; this.level=_1f9; this.info=info; this.timestamp=new Date(); }; MochiKit.Logging.LogMessage.prototype={repr:function(){ var m=MochiKit.Base; return "LogMessage("+m.map(m.repr,[this.num,this.level,this.info]).join(", ")+")"; },toString:MochiKit.Base.forwardCall("repr")}; MochiKit.Base.update(MochiKit.Logging,{logLevelAtLeast:function(_1fc){ var self=MochiKit.Logging; if(typeof (_1fc)=="string"){ _1fc=self.LogLevel[_1fc]; } return function(msg){ var _1ff=msg.level; if(typeof (_1ff)=="string"){ _1ff=self.LogLevel[_1ff]; } return _1ff>=_1fc; }; },isLogMessage:function(){ var _200=MochiKit.Logging.LogMessage; for(var i=0;i=MochiKit.Logging.LogLevel.FATAL){ _20f="FATAL"; }else{ if(_20f>=MochiKit.Logging.LogLevel.ERROR){ _20f="ERROR"; }else{ if(_20f>=MochiKit.Logging.LogLevel.WARNING){ _20f="WARNING"; }else{ if(_20f>=MochiKit.Logging.LogLevel.INFO){ _20f="INFO"; }else{ _20f="DEBUG"; } } } } } var msg=new MochiKit.Logging.LogMessage(this.counter,_20f,MochiKit.Base.extend(null,arguments,1)); this._messages.push(msg); this.dispatchListeners(msg); if(this.useNativeConsole){ this.logToConsole(msg.level+": "+msg.info.join(" ")); } this.counter+=1; while(this.maxSize>=0&&this._messages.length>this.maxSize){ this._messages.shift(); } },getMessages:function(_212){ var _213=0; if(!(typeof (_212)=="undefined"||_212===null)){ _213=Math.max(0,this._messages.length-_212); } return this._messages.slice(_213); },getMessageText:function(_214){ if(typeof (_214)=="undefined"||_214===null){ _214=30; } var _215=this.getMessages(_214); if(_215.length){ var lst=map(function(m){ return "\n ["+m.num+"] "+m.level+": "+m.info.join(" "); },_215); lst.unshift("LAST "+_215.length+" MESSAGES:"); return lst.join(""); } return ""; },debuggingBookmarklet:function(_218){ if(typeof (MochiKit.LoggingPane)=="undefined"){ alert(this.getMessageText()); }else{ MochiKit.LoggingPane.createLoggingPane(_218||false); } }}; MochiKit.Logging.__new__=function(){ this.LogLevel={ERROR:40,FATAL:50,WARNING:30,INFO:20,DEBUG:10}; var m=MochiKit.Base; m.registerComparator("LogMessage",this.isLogMessage,this.compareLogMessage); var _21a=m.partial; var _21b=this.Logger; var _21c=_21b.prototype.baseLog; m.update(this.Logger.prototype,{debug:_21a(_21c,"DEBUG"),log:_21a(_21c,"INFO"),error:_21a(_21c,"ERROR"),fatal:_21a(_21c,"FATAL"),warning:_21a(_21c,"WARNING")}); var self=this; var _21e=function(name){ return function(){ self.logger[name].apply(self.logger,arguments); }; }; this.log=_21e("log"); this.logError=_21e("error"); this.logDebug=_21e("debug"); this.logFatal=_21e("fatal"); this.logWarning=_21e("warning"); this.logger=new _21b(); this.logger.useNativeConsole=true; this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }; if(typeof (printfire)=="undefined"&&typeof (document)!="undefined"&&document.createEvent&&typeof (dispatchEvent)!="undefined"){ printfire=function(){ printfire.args=arguments; var ev=document.createEvent("Events"); ev.initEvent("printfire",false,true); dispatchEvent(ev); }; } MochiKit.Logging.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.Logging); MochiKit.Base._deps("DateTime",["Base"]); MochiKit.DateTime.NAME="MochiKit.DateTime"; MochiKit.DateTime.VERSION="1.4.2"; MochiKit.DateTime.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.DateTime.toString=function(){ return this.__repr__(); }; MochiKit.DateTime.isoDate=function(str){ str=str+""; if(typeof (str)!="string"||str.length===0){ return null; } var iso=str.split("-"); if(iso.length===0){ return null; } var date=new Date(iso[0],iso[1]-1,iso[2]); date.setFullYear(iso[0]); date.setMonth(iso[1]-1); date.setDate(iso[2]); return date; }; MochiKit.DateTime._isoRegexp=/(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/; MochiKit.DateTime.isoTimestamp=function(str){ str=str+""; if(typeof (str)!="string"||str.length===0){ return null; } var res=str.match(MochiKit.DateTime._isoRegexp); if(typeof (res)=="undefined"||res===null){ return null; } var year,_227,day,hour,min,sec,msec; year=parseInt(res[1],10); if(typeof (res[2])=="undefined"||res[2]===""){ return new Date(year); } _227=parseInt(res[2],10)-1; day=parseInt(res[3],10); if(typeof (res[4])=="undefined"||res[4]===""){ return new Date(year,_227,day); } hour=parseInt(res[4],10); min=parseInt(res[5],10); sec=(typeof (res[6])!="undefined"&&res[6]!=="")?parseInt(res[6],10):0; if(typeof (res[7])!="undefined"&&res[7]!==""){ msec=Math.round(1000*parseFloat("0."+res[7])); }else{ msec=0; } if((typeof (res[8])=="undefined"||res[8]==="")&&(typeof (res[9])=="undefined"||res[9]==="")){ return new Date(year,_227,day,hour,min,sec,msec); } var ofs; if(typeof (res[9])!="undefined"&&res[9]!==""){ ofs=parseInt(res[10],10)*3600000; if(typeof (res[11])!="undefined"&&res[11]!==""){ ofs+=parseInt(res[11],10)*60000; } if(res[9]=="-"){ ofs=-ofs; } }else{ ofs=0; } return new Date(Date.UTC(year,_227,day,hour,min,sec,msec)-ofs); }; MochiKit.DateTime.toISOTime=function(date,_22f){ if(typeof (date)=="undefined"||date===null){ return null; } var hh=date.getHours(); var mm=date.getMinutes(); var ss=date.getSeconds(); var lst=[((_22f&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)]; return lst.join(":"); }; MochiKit.DateTime.toISOTimestamp=function(date,_235){ if(typeof (date)=="undefined"||date===null){ return null; } var sep=_235?"T":" "; var foot=_235?"Z":""; if(_235){ date=new Date(date.getTime()+(date.getTimezoneOffset()*60000)); } return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_235)+foot; }; MochiKit.DateTime.toISODate=function(date){ if(typeof (date)=="undefined"||date===null){ return null; } var _239=MochiKit.DateTime._padTwo; var _23a=MochiKit.DateTime._padFour; return [_23a(date.getFullYear()),_239(date.getMonth()+1),_239(date.getDate())].join("-"); }; MochiKit.DateTime.americanDate=function(d){ d=d+""; if(typeof (d)!="string"||d.length===0){ return null; } var a=d.split("/"); return new Date(a[2],a[0]-1,a[1]); }; MochiKit.DateTime._padTwo=function(n){ return (n>9)?n:"0"+n; }; MochiKit.DateTime._padFour=function(n){ switch(n.toString().length){ case 1: return "000"+n; break; case 2: return "00"+n; break; case 3: return "0"+n; break; case 4: default: return n; } }; MochiKit.DateTime.toPaddedAmericanDate=function(d){ if(typeof (d)=="undefined"||d===null){ return null; } var _240=MochiKit.DateTime._padTwo; return [_240(d.getMonth()+1),_240(d.getDate()),d.getFullYear()].join("/"); }; MochiKit.DateTime.toAmericanDate=function(d){ if(typeof (d)=="undefined"||d===null){ return null; } return [d.getMonth()+1,d.getDate(),d.getFullYear()].join("/"); }; MochiKit.DateTime.EXPORT=["isoDate","isoTimestamp","toISOTime","toISOTimestamp","toISODate","americanDate","toPaddedAmericanDate","toAmericanDate"]; MochiKit.DateTime.EXPORT_OK=[]; MochiKit.DateTime.EXPORT_TAGS={":common":MochiKit.DateTime.EXPORT,":all":MochiKit.DateTime.EXPORT}; MochiKit.DateTime.__new__=function(){ var base=this.NAME+"."; for(var k in this){ var o=this[k]; if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ try{ o.NAME=base+k; } catch(e){ } } } }; MochiKit.DateTime.__new__(); if(typeof (MochiKit.Base)!="undefined"){ MochiKit.Base._exportSymbols(this,MochiKit.DateTime); }else{ (function(_245,_246){ if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){ var all=_246.EXPORT_TAGS[":all"]; for(var i=0;i_250){ var i=_258.length-_250; res=fmt.separator+_258.substring(i,_258.length)+res; _258=_258.substring(0,i); } } res=_258+res; if(_24e>0){ while(frac.length<_251){ frac=frac+"0"; } res=res+fmt.decimal+frac; } return _253+res+_254; }; }; MochiKit.Format.numberFormatter=function(_25c,_25d,_25e){ if(typeof (_25d)=="undefined"){ _25d=""; } var _25f=_25c.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/); if(!_25f){ throw TypeError("Invalid pattern"); } var _260=_25c.substr(0,_25f.index); var _261=_25c.substr(_25f.index+_25f[0].length); if(_260.search(/-/)==-1){ _260=_260+"-"; } var _262=_25f[1]; var frac=(typeof (_25f[2])=="string"&&_25f[2]!="")?_25f[2]:""; var _264=(typeof (_25f[3])=="string"&&_25f[3]!=""); var tmp=_262.split(/,/); var _266; if(typeof (_25e)=="undefined"){ _25e="default"; } if(tmp.length==1){ _266=null; }else{ _266=tmp[1].length; } var _267=_262.length-_262.replace(/0/g,"").length; var _268=frac.length-frac.replace(/0/g,"").length; var _269=frac.length; var rval=MochiKit.Format._numberFormatter(_25d,_260,_261,_25e,_264,_269,_267,_266,_268); var m=MochiKit.Base; if(m){ var fn=arguments.callee; var args=m.concat(arguments); rval.repr=function(){ return [self.NAME,"(",map(m.repr,args).join(", "),")"].join(""); }; } return rval; }; MochiKit.Format.formatLocale=function(_26e){ if(typeof (_26e)=="undefined"||_26e===null){ _26e="default"; } if(typeof (_26e)=="string"){ var rval=MochiKit.Format.LOCALE[_26e]; if(typeof (rval)=="string"){ rval=arguments.callee(rval); MochiKit.Format.LOCALE[_26e]=rval; } return rval; }else{ return _26e; } }; MochiKit.Format.twoDigitAverage=function(_270,_271){ if(_271){ var res=_270/_271; if(!isNaN(res)){ return MochiKit.Format.twoDigitFloat(res); } } return "0"; }; MochiKit.Format.twoDigitFloat=function(_273){ var res=roundToFixed(_273,2); if(res.indexOf(".00")>0){ return res.substring(0,res.length-3); }else{ if(res.charAt(res.length-1)=="0"){ return res.substring(0,res.length-1); }else{ return res; } } }; MochiKit.Format.lstrip=function(str,_276){ str=str+""; if(typeof (str)!="string"){ return null; } if(!_276){ return str.replace(/^\s+/,""); }else{ return str.replace(new RegExp("^["+_276+"]+"),""); } }; MochiKit.Format.rstrip=function(str,_278){ str=str+""; if(typeof (str)!="string"){ return null; } if(!_278){ return str.replace(/\s+$/,""); }else{ return str.replace(new RegExp("["+_278+"]+$"),""); } }; MochiKit.Format.strip=function(str,_27a){ var self=MochiKit.Format; return self.rstrip(self.lstrip(str,_27a),_27a); }; MochiKit.Format.truncToFixed=function(_27c,_27d){ var res=Math.floor(_27c).toFixed(0); if(_27c<0){ res=Math.ceil(_27c).toFixed(0); if(res.charAt(0)!="-"&&_27d>0){ res="-"+res; } } if(res.indexOf("e")<0&&_27d>0){ var tail=_27c.toString(); if(tail.indexOf("e")>0){ tail="."; }else{ if(tail.indexOf(".")<0){ tail="."; }else{ tail=tail.substring(tail.indexOf(".")); } } if(tail.length-1>_27d){ tail=tail.substring(0,_27d+1); } while(tail.length-1<_27d){ tail+="0"; } res+=tail; } return res; }; MochiKit.Format.roundToFixed=function(_280,_281){ var _282=Math.abs(_280)+0.5*Math.pow(10,-_281); var res=MochiKit.Format.truncToFixed(_282,_281); if(_280<0){ res="-"+res; } return res; }; MochiKit.Format.percentFormat=function(_284){ return MochiKit.Format.twoDigitFloat(100*_284)+"%"; }; MochiKit.Format.EXPORT=["truncToFixed","roundToFixed","numberFormatter","formatLocale","twoDigitAverage","twoDigitFloat","percentFormat","lstrip","rstrip","strip"]; MochiKit.Format.LOCALE={en_US:{separator:",",decimal:".",percent:"%"},de_DE:{separator:".",decimal:",",percent:"%"},pt_BR:{separator:".",decimal:",",percent:"%"},fr_FR:{separator:" ",decimal:",",percent:"%"},"default":"en_US"}; MochiKit.Format.EXPORT_OK=[]; MochiKit.Format.EXPORT_TAGS={":all":MochiKit.Format.EXPORT,":common":MochiKit.Format.EXPORT}; MochiKit.Format.__new__=function(){ var base=this.NAME+"."; var k,v,o; for(k in this.LOCALE){ o=this.LOCALE[k]; if(typeof (o)=="object"){ o.repr=function(){ return this.NAME; }; o.NAME=base+"LOCALE."+k; } } for(k in this){ o=this[k]; if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){ try{ o.NAME=base+k; } catch(e){ } } } }; MochiKit.Format.__new__(); if(typeof (MochiKit.Base)!="undefined"){ MochiKit.Base._exportSymbols(this,MochiKit.Format); }else{ (function(_289,_28a){ if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){ var all=_28a.EXPORT_TAGS[":all"]; for(var i=0;i1){ fn=MochiKit.Base.partial.apply(null,arguments); } return this.addCallbacks(fn,fn); },addCallback:function(fn){ if(arguments.length>1){ fn=MochiKit.Base.partial.apply(null,arguments); } return this.addCallbacks(fn,null); },addErrback:function(fn){ if(arguments.length>1){ fn=MochiKit.Base.partial.apply(null,arguments); } return this.addCallbacks(null,fn); },addCallbacks:function(cb,eb){ if(this.chained){ throw new Error("Chained Deferreds can not be re-used"); } this.chain.push([cb,eb]); if(this.fired>=0){ this._fire(); } return this; },_fire:function(){ var _299=this.chain; var _29a=this.fired; var res=this.results[_29a]; var self=this; var cb=null; while(_299.length>0&&this.paused===0){ var pair=_299.shift(); var f=pair[_29a]; if(f===null){ continue; } try{ res=f(res); _29a=((res instanceof Error)?1:0); if(res instanceof MochiKit.Async.Deferred){ cb=function(res){ self._resback(res); self.paused--; if((self.paused===0)&&(self.fired>=0)){ self._fire(); } }; this.paused++; } } catch(err){ _29a=1; if(!(err instanceof Error)){ err=new MochiKit.Async.GenericError(err); } res=err; } } this.fired=_29a; this.results[_29a]=res; if(cb&&this.paused){ res.addBoth(cb); res.chained=true; } }}; MochiKit.Base.update(MochiKit.Async,{evalJSONRequest:function(req){ return MochiKit.Base.evalJSON(req.responseText); },succeed:function(_2a2){ var d=new MochiKit.Async.Deferred(); d.callback.apply(d,arguments); return d; },fail:function(_2a4){ var d=new MochiKit.Async.Deferred(); d.errback.apply(d,arguments); return d; },getXMLHttpRequest:function(){ var self=arguments.callee; if(!self.XMLHttpRequest){ var _2a7=[function(){ return new XMLHttpRequest(); },function(){ return new ActiveXObject("Msxml2.XMLHTTP"); },function(){ return new ActiveXObject("Microsoft.XMLHTTP"); },function(){ return new ActiveXObject("Msxml2.XMLHTTP.4.0"); },function(){ throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest"); }]; for(var i=0;i<_2a7.length;i++){ var func=_2a7[i]; try{ self.XMLHttpRequest=func; return func(); } catch(e){ } } } return self.XMLHttpRequest(); },_xhr_onreadystatechange:function(d){ var m=MochiKit.Base; if(this.readyState==4){ try{ this.onreadystatechange=null; } catch(e){ try{ this.onreadystatechange=m.noop; } catch(e){ } } var _2ac=null; try{ _2ac=this.status; if(!_2ac&&m.isNotEmpty(this.responseText)){ _2ac=304; } } catch(e){ } if(_2ac==200||_2ac==201||_2ac==204||_2ac==304||_2ac==1223){ d.callback(this); }else{ var err=new MochiKit.Async.XMLHttpRequestError(this,"Request failed"); if(err.number){ d.errback(err); }else{ d.errback(err); } } } },_xhr_canceller:function(req){ try{ req.onreadystatechange=null; } catch(e){ try{ req.onreadystatechange=MochiKit.Base.noop; } catch(e){ } } req.abort(); },sendXMLHttpRequest:function(req,_2b0){ if(typeof (_2b0)=="undefined"||_2b0===null){ _2b0=""; } var m=MochiKit.Base; var self=MochiKit.Async; var d=new self.Deferred(m.partial(self._xhr_canceller,req)); try{ req.onreadystatechange=m.bind(self._xhr_onreadystatechange,req,d); req.send(_2b0); } catch(e){ try{ req.onreadystatechange=null; } catch(ignore){ } d.errback(e); } return d; },doXHR:function(url,opts){ var self=MochiKit.Async; return self.callLater(0,self._doXHR,url,opts); },_doXHR:function(url,opts){ var m=MochiKit.Base; opts=m.update({method:"GET",sendContent:""},opts); var self=MochiKit.Async; var req=self.getXMLHttpRequest(); if(opts.queryString){ var qs=m.queryString(opts.queryString); if(qs){ url+="?"+qs; } } if("username" in opts){ req.open(opts.method,url,true,opts.username,opts.password); }else{ req.open(opts.method,url,true); } if(req.overrideMimeType&&opts.mimeType){ req.overrideMimeType(opts.mimeType); } req.setRequestHeader("X-Requested-With","XMLHttpRequest"); if(opts.headers){ var _2bd=opts.headers; if(!m.isArrayLike(_2bd)){ _2bd=m.items(_2bd); } for(var i=0;i<_2bd.length;i++){ var _2bf=_2bd[i]; var name=_2bf[0]; var _2c1=_2bf[1]; req.setRequestHeader(name,_2c1); } } return self.sendXMLHttpRequest(req,opts.sendContent); },_buildURL:function(url){ if(arguments.length>1){ var m=MochiKit.Base; var qs=m.queryString.apply(null,m.extend(null,arguments,1)); if(qs){ return url+"?"+qs; } } return url; },doSimpleXMLHttpRequest:function(url){ var self=MochiKit.Async; url=self._buildURL.apply(self,arguments); return self.doXHR(url); },loadJSONDoc:function(url){ var self=MochiKit.Async; url=self._buildURL.apply(self,arguments); var d=self.doXHR(url,{"mimeType":"text/plain","headers":[["Accept","application/json"]]}); d=d.addCallback(self.evalJSONRequest); return d; },wait:function(_2ca,_2cb){ var d=new MochiKit.Async.Deferred(); var m=MochiKit.Base; if(typeof (_2cb)!="undefined"){ d.addCallback(function(){ return _2cb; }); } var _2ce=setTimeout(m.bind("callback",d),Math.floor(_2ca*1000)); d.canceller=function(){ try{ clearTimeout(_2ce); } catch(e){ } }; return d; },callLater:function(_2cf,func){ var m=MochiKit.Base; var _2d2=m.partial.apply(m,m.extend(null,arguments,1)); return MochiKit.Async.wait(_2cf).addCallback(function(res){ return _2d2(); }); }}); MochiKit.Async.DeferredLock=function(){ this.waiting=[]; this.locked=false; this.id=this._nextId(); }; MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){ var d=new MochiKit.Async.Deferred(); if(this.locked){ this.waiting.push(d); }else{ this.locked=true; d.callback(this); } return d; },release:function(){ if(!this.locked){ throw TypeError("Tried to release an unlocked DeferredLock"); } this.locked=false; if(this.waiting.length>0){ this.locked=true; this.waiting.shift().callback(this); } },_nextId:MochiKit.Base.counter(),repr:function(){ var _2d5; if(this.locked){ _2d5="locked, "+this.waiting.length+" waiting"; }else{ _2d5="unlocked"; } return "DeferredLock("+this.id+", "+_2d5+")"; },toString:MochiKit.Base.forwardCall("repr")}; MochiKit.Async.DeferredList=function(list,_2d7,_2d8,_2d9,_2da){ MochiKit.Async.Deferred.apply(this,[_2da]); this.list=list; var _2db=[]; this.resultList=_2db; this.finishedCount=0; this.fireOnOneCallback=_2d7; this.fireOnOneErrback=_2d8; this.consumeErrors=_2d9; var cb=MochiKit.Base.bind(this._cbDeferred,this); for(var i=0;i=0){ var opt=elem.options[elem.selectedIndex]; var v=opt.value; if(!v){ var h=opt.outerHTML; if(h&&!h.match(/^[^>]+\svalue\s*=/i)){ v=opt.text; } } _2fa.push(name); _2fb.push(v); return null; } _2fa.push(name); _2fb.push(""); return null; }else{ var opts=elem.options; if(!opts.length){ _2fa.push(name); _2fb.push(""); return null; } for(var i=0;i]+\svalue\s*=/i)){ v=opt.text; } } _2fa.push(name); _2fb.push(v); } return null; } } if(_300==="FORM"||_300==="P"||_300==="SPAN"||_300==="DIV"){ return elem.childNodes; } _2fa.push(name); _2fb.push(elem.value||""); return null; } return elem.childNodes; }); return [_2fa,_2fb]; },withDocument:function(doc,func){ var self=MochiKit.DOM; var _309=self._document; var rval; try{ self._document=doc; rval=func(); } catch(e){ self._document=_309; throw e; } self._document=_309; return rval; },registerDOMConverter:function(name,_30c,wrap,_30e){ MochiKit.DOM.domConverters.register(name,_30c,wrap,_30e); },coerceToDOM:function(node,ctx){ var m=MochiKit.Base; var im=MochiKit.Iter; var self=MochiKit.DOM; if(im){ var iter=im.iter; var _315=im.repeat; } var map=m.map; var _317=self.domConverters; var _318=arguments.callee; var _319=m.NotFound; while(true){ if(typeof (node)=="undefined"||node===null){ return null; } if(typeof (node)=="function"&&typeof (node.length)=="number"&&!(node instanceof Function)){ node=im?im.list(node):m.extend(null,node); } if(typeof (node.nodeType)!="undefined"&&node.nodeType>0){ return node; } if(typeof (node)=="number"||typeof (node)=="boolean"){ node=node.toString(); } if(typeof (node)=="string"){ return self._document.createTextNode(node); } if(typeof (node.__dom__)=="function"){ node=node.__dom__(ctx); continue; } if(typeof (node.dom)=="function"){ node=node.dom(ctx); continue; } if(typeof (node)=="function"){ node=node.apply(ctx,[ctx]); continue; } if(im){ var _31a=null; try{ _31a=iter(node); } catch(e){ } if(_31a){ return map(_318,_31a,_315(ctx)); } }else{ if(m.isArrayLike(node)){ var func=function(n){ return _318(n,ctx); }; return map(func,node); } } try{ node=_317.match(node,ctx); continue; } catch(e){ if(e!=_319){ throw e; } } return self._document.createTextNode(node.toString()); } return undefined; },isChildNode:function(node,_31e){ var self=MochiKit.DOM; if(typeof (node)=="string"){ node=self.getElement(node); } if(typeof (_31e)=="string"){ _31e=self.getElement(_31e); } if(typeof (node)=="undefined"||node===null){ return false; } while(node!=null&&node!==self._document){ if(node===_31e){ return true; } node=node.parentNode; } return false; },setNodeAttribute:function(node,attr,_322){ var o={}; o[attr]=_322; try{ return MochiKit.DOM.updateNodeAttributes(node,o); } catch(e){ } return null; },getNodeAttribute:function(node,attr){ var self=MochiKit.DOM; var _327=self.attributeArray.renames[attr]; var _328=self.attributeArray.ignoreAttr[attr]; node=self.getElement(node); try{ if(_327){ return node[_327]; } var _329=node.getAttribute(attr); if(_329!=_328){ return _329; } } catch(e){ } return null; },removeNodeAttribute:function(node,attr){ var self=MochiKit.DOM; var _32d=self.attributeArray.renames[attr]; node=self.getElement(node); try{ if(_32d){ return node[_32d]; } return node.removeAttribute(attr); } catch(e){ } return null; },updateNodeAttributes:function(node,_32f){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); } if(_32f){ var _332=MochiKit.Base.updatetree; if(self.attributeArray.compliant){ for(var k in _32f){ var v=_32f[k]; if(typeof (v)=="object"&&typeof (elem[k])=="object"){ if(k=="style"&&MochiKit.Style){ MochiKit.Style.setStyle(elem,v); }else{ _332(elem[k],v); } }else{ if(k.substring(0,2)=="on"){ if(typeof (v)=="string"){ v=new Function(v); } elem[k]=v; }else{ elem.setAttribute(k,v); } } if(typeof (elem[k])=="string"&&elem[k]!=v){ elem[k]=v; } } }else{ var _335=self.attributeArray.renames; for(var k in _32f){ v=_32f[k]; var _336=_335[k]; if(k=="style"&&typeof (v)=="string"){ elem.style.cssText=v; }else{ if(typeof (_336)=="string"){ elem[_336]=v; }else{ if(typeof (elem[k])=="object"&&typeof (v)=="object"){ if(k=="style"&&MochiKit.Style){ MochiKit.Style.setStyle(elem,v); }else{ _332(elem[k],v); } }else{ if(k.substring(0,2)=="on"){ if(typeof (v)=="string"){ v=new Function(v); } elem[k]=v; }else{ elem.setAttribute(k,v); } } } } if(typeof (elem[k])=="string"&&elem[k]!=v){ elem[k]=v; } } } } return elem; },appendChildNodes:function(node){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); } var _33a=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)]; var _33b=MochiKit.Base.concat; while(_33a.length){ var n=_33a.shift(); if(typeof (n)=="undefined"||n===null){ }else{ if(typeof (n.nodeType)=="number"){ elem.appendChild(n); }else{ _33a=_33b(n,_33a); } } } return elem; },insertSiblingNodesBefore:function(node){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); } var _340=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)]; var _341=elem.parentNode; var _342=MochiKit.Base.concat; while(_340.length){ var n=_340.shift(); if(typeof (n)=="undefined"||n===null){ }else{ if(typeof (n.nodeType)=="number"){ _341.insertBefore(n,elem); }else{ _340=_342(n,_340); } } } return _341; },insertSiblingNodesAfter:function(node){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); } var _347=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)]; if(elem.nextSibling){ return self.insertSiblingNodesBefore(elem.nextSibling,_347); }else{ return self.appendChildNodes(elem.parentNode,_347); } },replaceChildNodes:function(node){ var elem=node; var self=MochiKit.DOM; if(typeof (node)=="string"){ elem=self.getElement(node); arguments[0]=elem; } var _34b; while((_34b=elem.firstChild)){ elem.removeChild(_34b); } if(arguments.length<2){ return elem; }else{ return self.appendChildNodes.apply(this,arguments); } },createDOM:function(name,_34d){ var elem; var self=MochiKit.DOM; var m=MochiKit.Base; if(typeof (_34d)=="string"||typeof (_34d)=="number"){ var args=m.extend([name,null],arguments,1); return arguments.callee.apply(this,args); } if(typeof (name)=="string"){ var _352=self._xhtml; if(_34d&&!self.attributeArray.compliant){ var _353=""; if("name" in _34d){ _353+=" name=\""+self.escapeHTML(_34d.name)+"\""; } if(name=="input"&&"type" in _34d){ _353+=" type=\""+self.escapeHTML(_34d.type)+"\""; } if(_353){ name="<"+name+_353+">"; _352=false; } } var d=self._document; if(_352&&d===document){ elem=d.createElementNS("http://www.w3.org/1999/xhtml",name); }else{ elem=d.createElement(name); } }else{ elem=name; } if(_34d){ self.updateNodeAttributes(elem,_34d); } if(arguments.length<=2){ return elem; }else{ var args=m.extend([elem],arguments,2); return self.appendChildNodes.apply(this,args); } },createDOMFunc:function(){ var m=MochiKit.Base; return m.partial.apply(this,m.extend([MochiKit.DOM.createDOM],arguments)); },removeElement:function(elem){ var self=MochiKit.DOM; var e=self.coerceToDOM(self.getElement(elem)); e.parentNode.removeChild(e); return e; },swapDOM:function(dest,src){ var self=MochiKit.DOM; dest=self.getElement(dest); var _35c=dest.parentNode; if(src){ src=self.coerceToDOM(self.getElement(src),_35c); _35c.replaceChild(src,dest); }else{ _35c.removeChild(dest); } return src; },getElement:function(id){ var self=MochiKit.DOM; if(arguments.length==1){ return ((typeof (id)=="string")?self._document.getElementById(id):id); }else{ return MochiKit.Base.map(self.getElement,arguments); } },getElementsByTagAndClassName:function(_35f,_360,_361){ var self=MochiKit.DOM; if(typeof (_35f)=="undefined"||_35f===null){ _35f="*"; } if(typeof (_361)=="undefined"||_361===null){ _361=self._document; } _361=self.getElement(_361); if(_361==null){ return []; } var _363=(_361.getElementsByTagName(_35f)||self._document.all); if(typeof (_360)=="undefined"||_360===null){ return MochiKit.Base.extend(null,_363); } var _364=[]; for(var i=0;i<_363.length;i++){ var _366=_363[i]; var cls=_366.className; if(typeof (cls)!="string"){ cls=_366.getAttribute("class"); } if(typeof (cls)=="string"){ var _368=cls.split(" "); for(var j=0;j<_368.length;j++){ if(_368[j]==_360){ _364.push(_366); break; } } } } return _364; },_newCallStack:function(path,once){ var rval=function(){ var _36d=arguments.callee.callStack; for(var i=0;i<_36d.length;i++){ if(_36d[i].apply(this,arguments)===false){ break; } } if(once){ try{ this[path]=null; } catch(e){ } } }; rval.callStack=[]; return rval; },addToCallStack:function(_36f,path,func,once){ var self=MochiKit.DOM; var _374=_36f[path]; var _375=_374; if(!(typeof (_374)=="function"&&typeof (_374.callStack)=="object"&&_374.callStack!==null)){ _375=self._newCallStack(path,once); if(typeof (_374)=="function"){ _375.callStack.push(_374); } _36f[path]=_375; } _375.callStack.push(func); },addLoadEvent:function(func){ var self=MochiKit.DOM; self.addToCallStack(self._window,"onload",func,true); },focusOnLoad:function(_378){ var self=MochiKit.DOM; self.addLoadEvent(function(){ _378=self.getElement(_378); if(_378){ _378.focus(); } }); },setElementClass:function(_37a,_37b){ var self=MochiKit.DOM; var obj=self.getElement(_37a); if(self.attributeArray.compliant){ obj.setAttribute("class",_37b); }else{ obj.setAttribute("className",_37b); } },toggleElementClass:function(_37e){ var self=MochiKit.DOM; for(var i=1;i/g,">"); },toHTML:function(dom){ return MochiKit.DOM.emitHTML(dom).join(""); },emitHTML:function(dom,lst){ if(typeof (lst)=="undefined"||lst===null){ lst=[]; } var _3a1=[dom]; var self=MochiKit.DOM; var _3a3=self.escapeHTML; var _3a4=self.attributeArray; while(_3a1.length){ dom=_3a1.pop(); if(typeof (dom)=="string"){ lst.push(dom); }else{ if(dom.nodeType==1){ lst.push("<"+dom.tagName.toLowerCase()); var _3a5=[]; var _3a6=_3a4(dom); for(var i=0;i<_3a6.length;i++){ var a=_3a6[i]; _3a5.push([" ",a.name,"=\"",_3a3(a.value),"\""]); } _3a5.sort(); for(i=0;i<_3a5.length;i++){ var _3a9=_3a5[i]; for(var j=0;j<_3a9.length;j++){ lst.push(_3a9[j]); } } if(dom.hasChildNodes()){ lst.push(">"); _3a1.push(""); var _3ab=dom.childNodes; for(i=_3ab.length-1;i>=0;i--){ _3a1.push(_3ab[i]); } }else{ lst.push("/>"); } }else{ if(dom.nodeType==3){ lst.push(_3a3(dom.nodeValue)); } } } } return lst; },scrapeText:function(node,_3ad){ var rval=[]; (function(node){ var cn=node.childNodes; if(cn){ for(var i=0;i0){ var _3ca=m.filter; _3c9=function(node){ return _3ca(_3c9.ignoreAttrFilter,node.attributes); }; _3c9.ignoreAttr={}; var _3cc=_3c8.attributes; var _3cd=_3c9.ignoreAttr; for(var i=0;i<_3cc.length;i++){ var a=_3cc[i]; _3cd[a.name]=a.value; } _3c9.ignoreAttrFilter=function(a){ return (_3c9.ignoreAttr[a.name]!=a.value); }; _3c9.compliant=false; _3c9.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor","readonly":"readOnly","colspan":"colSpan","bgcolor":"bgColor","cellspacing":"cellSpacing","cellpadding":"cellPadding"}; }else{ _3c9=function(node){ return node.attributes; }; _3c9.compliant=true; _3c9.ignoreAttr={}; _3c9.renames={}; } this.attributeArray=_3c9; var _3d2=function(_3d3,arr){ var _3d5=arr[0]; var _3d6=arr[1]; var _3d7=_3d6.split(".")[1]; var str=""; str+="if (!MochiKit."+_3d7+") { throw new Error(\""; str+="This function has been deprecated and depends on MochiKit."; str+=_3d7+".\");}"; str+="return "+_3d6+".apply(this, arguments);"; MochiKit[_3d3][_3d5]=new Function(str); }; for(var i=0;i0){ abort(repr(expr)); } },buildMatchExpression:function(){ var repr=MochiKit.Base.repr; var _3e4=this.params; var _3e5=[]; var _3e6,i; function childElements(_3e8){ return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, "+_3e8+".childNodes)"; } if(_3e4.wildcard){ _3e5.push("true"); } if(_3e6=_3e4.id){ _3e5.push("element.id == "+repr(_3e6)); } if(_3e6=_3e4.tagName){ _3e5.push("element.tagName.toUpperCase() == "+repr(_3e6)); } if((_3e6=_3e4.classNames).length>0){ for(i=0;i<_3e6.length;i++){ _3e5.push("MochiKit.DOM.hasElementClass(element, "+repr(_3e6[i])+")"); } } if((_3e6=_3e4.pseudoClassNames).length>0){ for(i=0;i<_3e6.length;i++){ var _3e9=_3e6[i].match(/^([^(]+)(?:\((.*)\))?$/); var _3ea=_3e9[1]; var _3eb=_3e9[2]; switch(_3ea){ case "root": _3e5.push("element.nodeType == 9 || element === element.ownerDocument.documentElement"); break; case "nth-child": case "nth-last-child": case "nth-of-type": case "nth-last-of-type": _3e9=_3eb.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/); if(!_3e9){ throw "Invalid argument to pseudo element nth-child: "+_3eb; } var a,b; if(_3e9[0]=="odd"){ a=2; b=1; }else{ if(_3e9[0]=="even"){ a=2; b=0; }else{ a=_3e9[2]&&parseInt(_3e9)||null; b=parseInt(_3e9[3]); } } _3e5.push("this.nthChild(element,"+a+","+b+","+!!_3ea.match("^nth-last")+","+!!_3ea.match("of-type$")+")"); break; case "first-child": _3e5.push("this.nthChild(element, null, 1)"); break; case "last-child": _3e5.push("this.nthChild(element, null, 1, true)"); break; case "first-of-type": _3e5.push("this.nthChild(element, null, 1, false, true)"); break; case "last-of-type": _3e5.push("this.nthChild(element, null, 1, true, true)"); break; case "only-child": _3e5.push(childElements("element.parentNode")+".length == 1"); break; case "only-of-type": _3e5.push("MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, "+childElements("element.parentNode")+").length == 1"); break; case "empty": _3e5.push("element.childNodes.length == 0"); break; case "enabled": _3e5.push("(this.isUIElement(element) && element.disabled === false)"); break; case "disabled": _3e5.push("(this.isUIElement(element) && element.disabled === true)"); break; case "checked": _3e5.push("(this.isUIElement(element) && element.checked === true)"); break; case "not": var _3ee=new MochiKit.Selector.Selector(_3eb); _3e5.push("!( "+_3ee.buildMatchExpression()+")"); break; } } } if(_3e6=_3e4.attributes){ MochiKit.Base.map(function(_3ef){ var _3f0="MochiKit.DOM.getNodeAttribute(element, "+repr(_3ef.name)+")"; var _3f1=function(_3f2){ return _3f0+".split("+repr(_3f2)+")"; }; _3e5.push(_3f0+" != null"); switch(_3ef.operator){ case "=": _3e5.push(_3f0+" == "+repr(_3ef.value)); break; case "~=": _3e5.push("MochiKit.Base.findValue("+_3f1(" ")+", "+repr(_3ef.value)+") > -1"); break; case "^=": _3e5.push(_3f0+".substring(0, "+_3ef.value.length+") == "+repr(_3ef.value)); break; case "$=": _3e5.push(_3f0+".substring("+_3f0+".length - "+_3ef.value.length+") == "+repr(_3ef.value)); break; case "*=": _3e5.push(_3f0+".match("+repr(_3ef.value)+")"); break; case "|=": _3e5.push(_3f1("-")+"[0].toUpperCase() == "+repr(_3ef.value.toUpperCase())); break; case "!=": _3e5.push(_3f0+" != "+repr(_3ef.value)); break; case "": case undefined: break; default: throw "Unknown operator "+_3ef.operator+" in selector"; } },_3e6); } return _3e5.join(" && "); },compileMatcher:function(){ var code="return (!element.tagName) ? false : "+this.buildMatchExpression()+";"; this.match=new Function("element",code); },nthChild:function(_3f4,a,b,_3f7,_3f8){ var _3f9=MochiKit.Base.filter(function(node){ return node.nodeType==1; },_3f4.parentNode.childNodes); if(_3f8){ _3f9=MochiKit.Base.filter(function(node){ return node.tagName==_3f4.tagName; },_3f9); } if(_3f7){ _3f9=MochiKit.Iter.reversed(_3f9); } if(a){ var _3fc=MochiKit.Base.findIdentical(_3f9,_3f4); return ((_3fc+1-b)/a)%1==0; }else{ return b==MochiKit.Base.findIdentical(_3f9,_3f4)+1; } },isUIElement:function(_3fd){ return MochiKit.Base.findValue(["input","button","select","option","textarea","object"],_3fd.tagName.toLowerCase())>-1; },findElements:function(_3fe,axis){ var _400; if(axis==undefined){ axis=""; } function inScope(_401,_402){ if(axis==""){ return MochiKit.DOM.isChildNode(_401,_402); }else{ if(axis==">"){ return _401.parentNode===_402; }else{ if(axis=="+"){ return _401===nextSiblingElement(_402); }else{ if(axis=="~"){ var _403=_402; while(_403=nextSiblingElement(_403)){ if(_401===_403){ return true; } } return false; }else{ throw "Invalid axis: "+axis; } } } } } if(_400=MochiKit.DOM.getElement(this.params.id)){ if(this.match(_400)){ if(!_3fe||inScope(_400,_3fe)){ return [_400]; } } } function nextSiblingElement(node){ node=node.nextSibling; while(node&&node.nodeType!=1){ node=node.nextSibling; } return node; } if(axis==""){ _3fe=(_3fe||MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName||"*"); }else{ if(axis==">"){ if(!_3fe){ throw "> combinator not allowed without preceeding expression"; } _3fe=MochiKit.Base.filter(function(node){ return node.nodeType==1; },_3fe.childNodes); }else{ if(axis=="+"){ if(!_3fe){ throw "+ combinator not allowed without preceeding expression"; } _3fe=nextSiblingElement(_3fe)&&[nextSiblingElement(_3fe)]; }else{ if(axis=="~"){ if(!_3fe){ throw "~ combinator not allowed without preceeding expression"; } var _406=[]; while(nextSiblingElement(_3fe)){ _3fe=nextSiblingElement(_3fe); _406.push(_3fe); } _3fe=_406; } } } } if(!_3fe){ return []; } var _407=MochiKit.Base.filter(MochiKit.Base.bind(function(_408){ return this.match(_408); },this),_3fe); return _407; },repr:function(){ return "Selector("+this.expression+")"; },toString:MochiKit.Base.forwardCall("repr")}; MochiKit.Base.update(MochiKit.Selector,{findChildElements:function(_409,_40a){ var uniq=function(arr){ var res=[]; for(var i=0;i+~]$/)){ _410=match[0]; return _412; }else{ var _414=new MochiKit.Selector.Selector(expr); var _415=MochiKit.Iter.reduce(function(_416,_417){ return MochiKit.Base.extend(_416,_414.findElements(_417||_409,_410)); },_412,[]); _410=""; return _415; } }; var _418=_40f.replace(/(^\s+|\s+$)/g,"").split(/\s+/); return uniq(MochiKit.Iter.reduce(_411,_418,[null])); },_40a)); },findDocElements:function(){ return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(),arguments); },__new__:function(){ var m=MochiKit.Base; this.$$=this.findDocElements; this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }}); MochiKit.Selector.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.Selector); MochiKit.Base._deps("Style",["Base","DOM"]); MochiKit.Style.NAME="MochiKit.Style"; MochiKit.Style.VERSION="1.4.2"; MochiKit.Style.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Style.toString=function(){ return this.__repr__(); }; MochiKit.Style.EXPORT_OK=[]; MochiKit.Style.EXPORT=["setStyle","setOpacity","getStyle","getElementDimensions","elementDimensions","setElementDimensions","getElementPosition","elementPosition","setElementPosition","makePositioned","undoPositioned","makeClipping","undoClipping","setDisplayForElement","hideElement","showElement","getViewportDimensions","getViewportPosition","Dimensions","Coordinates"]; MochiKit.Style.Dimensions=function(w,h){ this.w=w; this.h=h; }; MochiKit.Style.Dimensions.prototype.__repr__=function(){ var repr=MochiKit.Base.repr; return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}"; }; MochiKit.Style.Dimensions.prototype.toString=function(){ return this.__repr__(); }; MochiKit.Style.Coordinates=function(x,y){ this.x=x; this.y=y; }; MochiKit.Style.Coordinates.prototype.__repr__=function(){ var repr=MochiKit.Base.repr; return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}"; }; MochiKit.Style.Coordinates.prototype.toString=function(){ return this.__repr__(); }; MochiKit.Base.update(MochiKit.Style,{getStyle:function(elem,_421){ var dom=MochiKit.DOM; var d=dom._document; elem=dom.getElement(elem); _421=MochiKit.Base.camelize(_421); if(!elem||elem==d){ return undefined; } if(_421=="opacity"&&typeof (elem.filters)!="undefined"){ var _424=(MochiKit.Style.getStyle(elem,"filter")||"").match(/alpha\(opacity=(.*)\)/); if(_424&&_424[1]){ return parseFloat(_424[1])/100; } return 1; } if(_421=="float"||_421=="cssFloat"||_421=="styleFloat"){ if(elem.style["float"]){ return elem.style["float"]; }else{ if(elem.style.cssFloat){ return elem.style.cssFloat; }else{ if(elem.style.styleFloat){ return elem.style.styleFloat; }else{ return "none"; } } } } var _425=elem.style?elem.style[_421]:null; if(!_425){ if(d.defaultView&&d.defaultView.getComputedStyle){ var css=d.defaultView.getComputedStyle(elem,null); _421=_421.replace(/([A-Z])/g,"-$1").toLowerCase(); _425=css?css.getPropertyValue(_421):null; }else{ if(elem.currentStyle){ _425=elem.currentStyle[_421]; if(/^\d/.test(_425)&&!/px$/.test(_425)&&_421!="fontWeight"){ var left=elem.style.left; var _428=elem.runtimeStyle.left; elem.runtimeStyle.left=elem.currentStyle.left; elem.style.left=_425||0; _425=elem.style.pixelLeft+"px"; elem.style.left=left; elem.runtimeStyle.left=_428; } } } } if(_421=="opacity"){ _425=parseFloat(_425); } if(/Opera/.test(navigator.userAgent)&&(MochiKit.Base.findValue(["left","top","right","bottom"],_421)!=-1)){ if(MochiKit.Style.getStyle(elem,"position")=="static"){ _425="auto"; } } return _425=="auto"?null:_425; },setStyle:function(elem,_42a){ elem=MochiKit.DOM.getElement(elem); for(var name in _42a){ switch(name){ case "opacity": MochiKit.Style.setOpacity(elem,_42a[name]); break; case "float": case "cssFloat": case "styleFloat": if(typeof (elem.style["float"])!="undefined"){ elem.style["float"]=_42a[name]; }else{ if(typeof (elem.style.cssFloat)!="undefined"){ elem.style.cssFloat=_42a[name]; }else{ elem.style.styleFloat=_42a[name]; } } break; default: elem.style[MochiKit.Base.camelize(name)]=_42a[name]; } } },setOpacity:function(elem,o){ elem=MochiKit.DOM.getElement(elem); var self=MochiKit.Style; if(o==1){ var _42f=/Gecko/.test(navigator.userAgent)&&!(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)); elem.style["opacity"]=_42f?0.999999:1; if(/MSIE/.test(navigator.userAgent)){ elem.style["filter"]=self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,""); } }else{ if(o<0.00001){ o=0; } elem.style["opacity"]=o; if(/MSIE/.test(navigator.userAgent)){ elem.style["filter"]=self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"")+"alpha(opacity="+o*100+")"; } } },getElementPosition:function(elem,_431){ var self=MochiKit.Style; var dom=MochiKit.DOM; elem=dom.getElement(elem); if(!elem||(!(elem.x&&elem.y)&&(!elem.parentNode===null||self.getStyle(elem,"display")=="none"))){ return undefined; } var c=new self.Coordinates(0,0); var box=null; var _436=null; var d=MochiKit.DOM._document; var de=d.documentElement; var b=d.body; if(!elem.parentNode&&elem.x&&elem.y){ c.x+=elem.x||0; c.y+=elem.y||0; }else{ if(elem.getBoundingClientRect){ box=elem.getBoundingClientRect(); c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0); c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||0); }else{ if(elem.offsetParent){ c.x+=elem.offsetLeft; c.y+=elem.offsetTop; _436=elem.offsetParent; if(_436!=elem){ while(_436){ c.x+=parseInt(_436.style.borderLeftWidth)||0; c.y+=parseInt(_436.style.borderTopWidth)||0; c.x+=_436.offsetLeft; c.y+=_436.offsetTop; _436=_436.offsetParent; } } var ua=navigator.userAgent.toLowerCase(); if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("AppleWebKit")!=-1&&self.getStyle(elem,"position")=="absolute")){ c.x-=b.offsetLeft; c.y-=b.offsetTop; } if(elem.parentNode){ _436=elem.parentNode; }else{ _436=null; } while(_436){ var _43b=_436.tagName.toUpperCase(); if(_43b==="BODY"||_43b==="HTML"){ break; } var disp=self.getStyle(_436,"display"); if(disp.search(/^inline|table-row.*$/i)){ c.x-=_436.scrollLeft; c.y-=_436.scrollTop; } if(_436.parentNode){ _436=_436.parentNode; }else{ _436=null; } } } } } if(typeof (_431)!="undefined"){ _431=arguments.callee(_431); if(_431){ c.x-=(_431.x||0); c.y-=(_431.y||0); } } return c; },setElementPosition:function(elem,_43e,_43f){ elem=MochiKit.DOM.getElement(elem); if(typeof (_43f)=="undefined"){ _43f="px"; } var _440={}; var _441=MochiKit.Base.isUndefinedOrNull; if(!_441(_43e.x)){ _440["left"]=_43e.x+_43f; } if(!_441(_43e.y)){ _440["top"]=_43e.y+_43f; } MochiKit.DOM.updateNodeAttributes(elem,{"style":_440}); },makePositioned:function(_442){ _442=MochiKit.DOM.getElement(_442); var pos=MochiKit.Style.getStyle(_442,"position"); if(pos=="static"||!pos){ _442.style.position="relative"; if(/Opera/.test(navigator.userAgent)){ _442.style.top=0; _442.style.left=0; } } },undoPositioned:function(_444){ _444=MochiKit.DOM.getElement(_444); if(_444.style.position=="relative"){ _444.style.position=_444.style.top=_444.style.left=_444.style.bottom=_444.style.right=""; } },makeClipping:function(_445){ _445=MochiKit.DOM.getElement(_445); var s=_445.style; var _447={"overflow":s.overflow,"overflow-x":s.overflowX,"overflow-y":s.overflowY}; if((MochiKit.Style.getStyle(_445,"overflow")||"visible")!="hidden"){ _445.style.overflow="hidden"; _445.style.overflowX="hidden"; _445.style.overflowY="hidden"; } return _447; },undoClipping:function(_448,_449){ _448=MochiKit.DOM.getElement(_448); if(typeof (_449)=="string"){ _448.style.overflow=_449; }else{ if(_449!=null){ _448.style.overflow=_449["overflow"]; _448.style.overflowX=_449["overflow-x"]; _448.style.overflowY=_449["overflow-y"]; } } },getElementDimensions:function(elem,_44b){ var self=MochiKit.Style; var dom=MochiKit.DOM; if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){ return new self.Dimensions(elem.w||0,elem.h||0); } elem=dom.getElement(elem); if(!elem){ return undefined; } var disp=self.getStyle(elem,"display"); if(disp=="none"||disp==""||typeof (disp)=="undefined"){ var s=elem.style; var _450=s.visibility; var _451=s.position; var _452=s.display; s.visibility="hidden"; s.position="absolute"; s.display=self._getDefaultDisplay(elem); var _453=elem.offsetWidth; var _454=elem.offsetHeight; s.display=_452; s.position=_451; s.visibility=_450; }else{ _453=elem.offsetWidth||0; _454=elem.offsetHeight||0; } if(_44b){ var _455="colSpan" in elem&&"rowSpan" in elem; var _456=(_455&&elem.parentNode&&self.getStyle(elem.parentNode,"borderCollapse")=="collapse"); if(_456){ if(/MSIE/.test(navigator.userAgent)){ var _457=elem.previousSibling?0.5:1; var _458=elem.nextSibling?0.5:1; }else{ var _457=0.5; var _458=0.5; } }else{ var _457=1; var _458=1; } _453-=Math.round((parseFloat(self.getStyle(elem,"paddingLeft"))||0)+(parseFloat(self.getStyle(elem,"paddingRight"))||0)+_457*(parseFloat(self.getStyle(elem,"borderLeftWidth"))||0)+_458*(parseFloat(self.getStyle(elem,"borderRightWidth"))||0)); if(_455){ if(/Gecko|Opera/.test(navigator.userAgent)&&!/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)){ var _459=0; }else{ if(/MSIE/.test(navigator.userAgent)){ var _459=1; }else{ var _459=_456?0.5:1; } } }else{ var _459=1; } _454-=Math.round((parseFloat(self.getStyle(elem,"paddingTop"))||0)+(parseFloat(self.getStyle(elem,"paddingBottom"))||0)+_459*((parseFloat(self.getStyle(elem,"borderTopWidth"))||0)+(parseFloat(self.getStyle(elem,"borderBottomWidth"))||0))); } return new self.Dimensions(_453,_454); },setElementDimensions:function(elem,_45b,_45c){ elem=MochiKit.DOM.getElement(elem); if(typeof (_45c)=="undefined"){ _45c="px"; } var _45d={}; var _45e=MochiKit.Base.isUndefinedOrNull; if(!_45e(_45b.w)){ _45d["width"]=_45b.w+_45c; } if(!_45e(_45b.h)){ _45d["height"]=_45b.h+_45c; } MochiKit.DOM.updateNodeAttributes(elem,{"style":_45d}); },_getDefaultDisplay:function(elem){ var self=MochiKit.Style; var dom=MochiKit.DOM; elem=dom.getElement(elem); if(!elem){ return undefined; } var _462=elem.tagName.toUpperCase(); return self._defaultDisplay[_462]||"block"; },setDisplayForElement:function(_463,_464){ var _465=MochiKit.Base.extend(null,arguments,1); var _466=MochiKit.DOM.getElement; for(var i=0;i<_465.length;i++){ _464=_466(_465[i]); if(_464){ _464.style.display=_463; } } },getViewportDimensions:function(){ var d=new MochiKit.Style.Dimensions(); var w=MochiKit.DOM._window; var b=MochiKit.DOM._document.body; if(w.innerWidth){ d.w=w.innerWidth; d.h=w.innerHeight; }else{ if(b&&b.parentElement&&b.parentElement.clientWidth){ d.w=b.parentElement.clientWidth; d.h=b.parentElement.clientHeight; }else{ if(b&&b.clientWidth){ d.w=b.clientWidth; d.h=b.clientHeight; } } } return d; },getViewportPosition:function(){ var c=new MochiKit.Style.Coordinates(0,0); var d=MochiKit.DOM._document; var de=d.documentElement; var db=d.body; if(de&&(de.scrollTop||de.scrollLeft)){ c.x=de.scrollLeft; c.y=de.scrollTop; }else{ if(db){ c.x=db.scrollLeft; c.y=db.scrollTop; } } return c; },__new__:function(){ var m=MochiKit.Base; var _470=["A","ABBR","ACRONYM","B","BASEFONT","BDO","BIG","BR","CITE","CODE","DFN","EM","FONT","I","IMG","KBD","LABEL","Q","S","SAMP","SMALL","SPAN","STRIKE","STRONG","SUB","SUP","TEXTAREA","TT","U","VAR"]; this._defaultDisplay={"TABLE":"table","THEAD":"table-header-group","TBODY":"table-row-group","TFOOT":"table-footer-group","COLGROUP":"table-column-group","COL":"table-column","TR":"table-row","TD":"table-cell","TH":"table-cell","CAPTION":"table-caption","LI":"list-item","INPUT":"inline-block","SELECT":"inline-block"}; if(/MSIE/.test(navigator.userAgent)){ for(var k in this._defaultDisplay){ var v=this._defaultDisplay[k]; if(v.indexOf("table")==0){ this._defaultDisplay[k]="block"; } } } for(var i=0;i<_470.length;i++){ this._defaultDisplay[_470[i]]="inline"; } this.elementPosition=this.getElementPosition; this.elementDimensions=this.getElementDimensions; this.hideElement=m.partial(this.setDisplayForElement,"none"); this.showElement=m.partial(this.setDisplayForElement,"block"); this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }}); MochiKit.Style.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.Style); MochiKit.Base._deps("LoggingPane",["Base","Logging"]); MochiKit.LoggingPane.NAME="MochiKit.LoggingPane"; MochiKit.LoggingPane.VERSION="1.4.2"; MochiKit.LoggingPane.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.LoggingPane.toString=function(){ return this.__repr__(); }; MochiKit.LoggingPane.createLoggingPane=function(_474){ var m=MochiKit.LoggingPane; _474=!(!_474); if(m._loggingPane&&m._loggingPane.inline!=_474){ m._loggingPane.closePane(); m._loggingPane=null; } if(!m._loggingPane||m._loggingPane.closed){ m._loggingPane=new m.LoggingPane(_474,MochiKit.Logging.logger); } return m._loggingPane; }; MochiKit.LoggingPane.LoggingPane=function(_476,_477){ if(typeof (_477)=="undefined"||_477===null){ _477=MochiKit.Logging.logger; } this.logger=_477; var _478=MochiKit.Base.update; var _479=MochiKit.Base.updatetree; var bind=MochiKit.Base.bind; var _47b=MochiKit.Base.clone; var win=window; var uid="_MochiKit_LoggingPane"; if(typeof (MochiKit.DOM)!="undefined"){ win=MochiKit.DOM.currentWindow(); } if(!_476){ var url=win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g,"_"); var name=uid+"_"+url; var nwin=win.open("",name,"dependent,resizable,height=200"); if(!nwin){ alert("Not able to open debugging window due to pop-up blocking."); return undefined; } nwin.document.write(""+"[MochiKit.LoggingPane]"+""); nwin.document.close(); nwin.document.title+=" "+win.document.title; win=nwin; } var doc=win.document; this.doc=doc; var _482=doc.getElementById(uid); var _483=!!_482; if(_482&&typeof (_482.loggingPane)!="undefined"){ _482.loggingPane.logger=this.logger; _482.loggingPane.buildAndApplyFilter(); return _482.loggingPane; } if(_483){ var _484; while((_484=_482.firstChild)){ _482.removeChild(_484); } }else{ _482=doc.createElement("div"); _482.id=uid; } _482.loggingPane=this; var _485=doc.createElement("input"); var _486=doc.createElement("input"); var _487=doc.createElement("button"); var _488=doc.createElement("button"); var _489=doc.createElement("button"); var _48a=doc.createElement("button"); var _48b=doc.createElement("div"); var _48c=doc.createElement("div"); var _48d=uid+"_Listener"; this.colorTable=_47b(this.colorTable); var _48e=[]; var _48f=null; var _490=function(msg){ var _492=msg.level; if(typeof (_492)=="number"){ _492=MochiKit.Logging.LogLevel[_492]; } return _492; }; var _493=function(msg){ return msg.info.join(" "); }; var _495=bind(function(msg){ var _497=_490(msg); var text=_493(msg); var c=this.colorTable[_497]; var p=doc.createElement("span"); p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_497; p.style.cssText="margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: "+c; p.appendChild(doc.createTextNode(_497+": "+text)); _48c.appendChild(p); _48c.appendChild(doc.createElement("br")); if(_48b.offsetHeight>_48b.scrollHeight){ _48b.scrollTop=0; }else{ _48b.scrollTop=_48b.scrollHeight; } },this); var _49b=function(msg){ _48e[_48e.length]=msg; _495(msg); }; var _49d=function(){ var _49e,_49f; try{ _49e=new RegExp(_485.value); _49f=new RegExp(_486.value); } catch(e){ logDebug("Error in filter regex: "+e.message); return null; } return function(msg){ return (_49e.test(_490(msg))&&_49f.test(_493(msg))); }; }; var _4a1=function(){ while(_48c.firstChild){ _48c.removeChild(_48c.firstChild); } }; var _4a2=function(){ _48e=[]; _4a1(); }; var _4a3=bind(function(){ if(this.closed){ return; } this.closed=true; if(MochiKit.LoggingPane._loggingPane==this){ MochiKit.LoggingPane._loggingPane=null; } this.logger.removeListener(_48d); try{ try{ _482.loggingPane=null; } catch(e){ logFatal("Bookmarklet was closed incorrectly."); } if(_476){ _482.parentNode.removeChild(_482); }else{ this.win.close(); } } catch(e){ } },this); var _4a4=function(){ _4a1(); for(var i=0;i<_48e.length;i++){ var msg=_48e[i]; if(_48f===null||_48f(msg)){ _495(msg); } } }; this.buildAndApplyFilter=function(){ _48f=_49d(); _4a4(); this.logger.removeListener(_48d); this.logger.addListener(_48d,_48f,_49b); }; var _4a7=bind(function(){ _48e=this.logger.getMessages(); _4a4(); },this); var _4a8=bind(function(_4a9){ _4a9=_4a9||window.event; key=_4a9.which||_4a9.keyCode; if(key==13){ this.buildAndApplyFilter(); } },this); var _4aa="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont; if(_476){ _4aa+="; height: 10em; border-top: 2px solid black"; }else{ _4aa+="; height: 100%;"; } _482.style.cssText=_4aa; if(!_483){ doc.body.appendChild(_482); } _4aa={"cssText":"width: 33%; display: inline; font: "+this.logFont}; _479(_485,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_4a8,"style":_4aa}); _482.appendChild(_485); _479(_486,{"value":".*","onkeypress":_4a8,"style":_4aa}); _482.appendChild(_486); _4aa="width: 8%; display:inline; font: "+this.logFont; _487.appendChild(doc.createTextNode("Filter")); _487.onclick=bind("buildAndApplyFilter",this); _487.style.cssText=_4aa; _482.appendChild(_487); _488.appendChild(doc.createTextNode("Load")); _488.onclick=_4a7; _488.style.cssText=_4aa; _482.appendChild(_488); _489.appendChild(doc.createTextNode("Clear")); _489.onclick=_4a2; _489.style.cssText=_4aa; _482.appendChild(_489); _48a.appendChild(doc.createTextNode("Close")); _48a.onclick=_4a3; _48a.style.cssText=_4aa; _482.appendChild(_48a); _48b.style.cssText="overflow: auto; width: 100%"; _48c.style.cssText="width: 100%; height: "+(_476?"8em":"100%"); _48b.appendChild(_48c); _482.appendChild(_48b); this.buildAndApplyFilter(); _4a7(); if(_476){ this.win=undefined; }else{ this.win=win; } this.inline=_476; this.closePane=_4a3; this.closed=false; return this; }; MochiKit.LoggingPane.LoggingPane.prototype={"logFont":"8pt Verdana,sans-serif","colorTable":{"ERROR":"red","FATAL":"darkred","WARNING":"blue","INFO":"black","DEBUG":"green"}}; MochiKit.LoggingPane.EXPORT_OK=["LoggingPane"]; MochiKit.LoggingPane.EXPORT=["createLoggingPane"]; MochiKit.LoggingPane.__new__=function(){ this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)}; MochiKit.Base.nameFunctions(this); MochiKit.LoggingPane._loggingPane=null; }; MochiKit.LoggingPane.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.LoggingPane); MochiKit.Base._deps("Color",["Base","DOM","Style"]); MochiKit.Color.NAME="MochiKit.Color"; MochiKit.Color.VERSION="1.4.2"; MochiKit.Color.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Color.toString=function(){ return this.__repr__(); }; MochiKit.Color.Color=function(red,_4ac,blue,_4ae){ if(typeof (_4ae)=="undefined"||_4ae===null){ _4ae=1; } this.rgb={r:red,g:_4ac,b:blue,a:_4ae}; }; MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_4af){ var rgb=this.rgb; var m=MochiKit.Color; return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_4af); },colorWithHue:function(hue){ var hsl=this.asHSL(); hsl.h=hue; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },colorWithSaturation:function(_4b5){ var hsl=this.asHSL(); hsl.s=_4b5; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },colorWithLightness:function(_4b8){ var hsl=this.asHSL(); hsl.l=_4b8; var m=MochiKit.Color; return m.Color.fromHSL(hsl); },darkerColorWithLevel:function(_4bb){ var hsl=this.asHSL(); hsl.l=Math.max(hsl.l-_4bb,0); var m=MochiKit.Color; return m.Color.fromHSL(hsl); },lighterColorWithLevel:function(_4be){ var hsl=this.asHSL(); hsl.l=Math.min(hsl.l+_4be,1); var m=MochiKit.Color; return m.Color.fromHSL(hsl); },blendedColor:function(_4c1,_4c2){ if(typeof (_4c2)=="undefined"||_4c2===null){ _4c2=0.5; } var sf=1-_4c2; var s=this.rgb; var d=_4c1.rgb; var df=_4c2; return MochiKit.Color.Color.fromRGB((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df)); },compareRGB:function(_4c7){ var a=this.asRGB(); var b=_4c7.asRGB(); return MochiKit.Base.compare([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a]); },isLight:function(){ return this.asHSL().b>0.5; },isDark:function(){ return (!this.isLight()); },toHSLString:function(){ var c=this.asHSL(); var ccc=MochiKit.Color.clampColorComponent; var rval=this._hslString; if(!rval){ var mid=(ccc(c.h,360).toFixed(0)+","+ccc(c.s,100).toPrecision(4)+"%"+","+ccc(c.l,100).toPrecision(4)+"%"); var a=c.a; if(a>=1){ a=1; rval="hsl("+mid+")"; }else{ if(a<=0){ a=0; } rval="hsla("+mid+","+a+")"; } this._hslString=rval; } return rval; },toRGBString:function(){ var c=this.rgb; var ccc=MochiKit.Color.clampColorComponent; var rval=this._rgbString; if(!rval){ var mid=(ccc(c.r,255).toFixed(0)+","+ccc(c.g,255).toFixed(0)+","+ccc(c.b,255).toFixed(0)); if(c.a!=1){ rval="rgba("+mid+","+c.a+")"; }else{ rval="rgb("+mid+")"; } this._rgbString=rval; } return rval; },asRGB:function(){ return MochiKit.Base.clone(this.rgb); },toHexString:function(){ var m=MochiKit.Color; var c=this.rgb; var ccc=MochiKit.Color.clampColorComponent; var rval=this._hexString; if(!rval){ rval=("#"+m.toColorPart(ccc(c.r,255))+m.toColorPart(ccc(c.g,255))+m.toColorPart(ccc(c.b,255))); this._hexString=rval; } return rval; },asHSV:function(){ var hsv=this.hsv; var c=this.rgb; if(typeof (hsv)=="undefined"||hsv===null){ hsv=MochiKit.Color.rgbToHSV(this.rgb); this.hsv=hsv; } return MochiKit.Base.clone(hsv); },asHSL:function(){ var hsl=this.hsl; var c=this.rgb; if(typeof (hsl)=="undefined"||hsl===null){ hsl=MochiKit.Color.rgbToHSL(this.rgb); this.hsl=hsl; } return MochiKit.Base.clone(hsl); },toString:function(){ return this.toRGBString(); },repr:function(){ var c=this.rgb; var col=[c.r,c.g,c.b,c.a]; return this.__class__.NAME+"("+col.join(", ")+")"; }}; MochiKit.Base.update(MochiKit.Color.Color,{fromRGB:function(red,_4de,blue,_4e0){ var _4e1=MochiKit.Color.Color; if(arguments.length==1){ var rgb=red; red=rgb.r; _4de=rgb.g; blue=rgb.b; if(typeof (rgb.a)=="undefined"){ _4e0=undefined; }else{ _4e0=rgb.a; } } return new _4e1(red,_4de,blue,_4e0); },fromHSL:function(hue,_4e4,_4e5,_4e6){ var m=MochiKit.Color; return m.Color.fromRGB(m.hslToRGB.apply(m,arguments)); },fromHSV:function(hue,_4e9,_4ea,_4eb){ var m=MochiKit.Color; return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments)); },fromName:function(name){ var _4ee=MochiKit.Color.Color; if(name.charAt(0)=="\""){ name=name.substr(1,name.length-2); } var _4ef=_4ee._namedColors[name.toLowerCase()]; if(typeof (_4ef)=="string"){ return _4ee.fromHexString(_4ef); }else{ if(name=="transparent"){ return _4ee.transparentColor(); } } return null; },fromString:function(_4f0){ var self=MochiKit.Color.Color; var _4f2=_4f0.substr(0,3); if(_4f2=="rgb"){ return self.fromRGBString(_4f0); }else{ if(_4f2=="hsl"){ return self.fromHSLString(_4f0); }else{ if(_4f0.charAt(0)=="#"){ return self.fromHexString(_4f0); } } } return self.fromName(_4f0); },fromHexString:function(_4f3){ if(_4f3.charAt(0)=="#"){ _4f3=_4f3.substring(1); } var _4f4=[]; var i,hex; if(_4f3.length==3){ for(i=0;i<3;i++){ hex=_4f3.substr(i,1); _4f4.push(parseInt(hex+hex,16)/255); } }else{ for(i=0;i<6;i+=2){ hex=_4f3.substr(i,2); _4f4.push(parseInt(hex,16)/255); } } var _4f7=MochiKit.Color.Color; return _4f7.fromRGB.apply(_4f7,_4f4); },_fromColorString:function(pre,_4f9,_4fa,_4fb){ if(_4fb.indexOf(pre)===0){ _4fb=_4fb.substring(_4fb.indexOf("(",3)+1,_4fb.length-1); } var _4fc=_4fb.split(/\s*,\s*/); var _4fd=[]; for(var i=0;i<_4fc.length;i++){ var c=_4fc[i]; var val; var _501=c.substring(c.length-3); if(c.charAt(c.length-1)=="%"){ val=0.01*parseFloat(c.substring(0,c.length-1)); }else{ if(_501=="deg"){ val=parseFloat(c)/360; }else{ if(_501=="rad"){ val=parseFloat(c)/(Math.PI*2); }else{ val=_4fa[i]*parseFloat(c); } } } _4fd.push(val); } return this[_4f9].apply(this,_4fd); },fromComputedStyle:function(elem,_503){ var d=MochiKit.DOM; var cls=MochiKit.Color.Color; for(elem=d.getElement(elem);elem;elem=elem.parentNode){ var _506=MochiKit.Style.getStyle.apply(d,arguments); if(!_506){ continue; } var _507=cls.fromString(_506); if(!_507){ break; } if(_507.asRGB().a>0){ return _507; } } return null; },fromBackground:function(elem){ var cls=MochiKit.Color.Color; return cls.fromComputedStyle(elem,"backgroundColor","background-color")||cls.whiteColor(); },fromText:function(elem){ var cls=MochiKit.Color.Color; return cls.fromComputedStyle(elem,"color","color")||cls.blackColor(); },namedColors:function(){ return MochiKit.Base.clone(MochiKit.Color.Color._namedColors); }}); MochiKit.Base.update(MochiKit.Color,{clampColorComponent:function(v,_50d){ v*=_50d; if(v<0){ return 0; }else{ if(v>_50d){ return _50d; }else{ return v; } } },_hslValue:function(n1,n2,hue){ if(hue>6){ hue-=6; }else{ if(hue<0){ hue+=6; } } var val; if(hue<1){ val=n1+(n2-n1)*hue; }else{ if(hue<3){ val=n2; }else{ if(hue<4){ val=n1+(n2-n1)*(4-hue); }else{ val=n1; } } } return val; },hsvToRGB:function(hue,_513,_514,_515){ if(arguments.length==1){ var hsv=hue; hue=hsv.h; _513=hsv.s; _514=hsv.v; _515=hsv.a; } var red; var _518; var blue; if(_513===0){ red=_514; _518=_514; blue=_514; }else{ var i=Math.floor(hue*6); var f=(hue*6)-i; var p=_514*(1-_513); var q=_514*(1-(_513*f)); var t=_514*(1-(_513*(1-f))); switch(i){ case 1: red=q; _518=_514; blue=p; break; case 2: red=p; _518=_514; blue=t; break; case 3: red=p; _518=q; blue=_514; break; case 4: red=t; _518=p; blue=_514; break; case 5: red=_514; _518=p; blue=q; break; case 6: case 0: red=_514; _518=t; blue=p; break; } } return {r:red,g:_518,b:blue,a:_515}; },hslToRGB:function(hue,_520,_521,_522){ if(arguments.length==1){ var hsl=hue; hue=hsl.h; _520=hsl.s; _521=hsl.l; _522=hsl.a; } var red; var _525; var blue; if(_520===0){ red=_521; _525=_521; blue=_521; }else{ var m2; if(_521<=0.5){ m2=_521*(1+_520); }else{ m2=_521+_520-(_521*_520); } var m1=(2*_521)-m2; var f=MochiKit.Color._hslValue; var h6=hue*6; red=f(m1,m2,h6+2); _525=f(m1,m2,h6); blue=f(m1,m2,h6-2); } return {r:red,g:_525,b:blue,a:_522}; },rgbToHSV:function(red,_52c,blue,_52e){ if(arguments.length==1){ var rgb=red; red=rgb.r; _52c=rgb.g; blue=rgb.b; _52e=rgb.a; } var max=Math.max(Math.max(red,_52c),blue); var min=Math.min(Math.min(red,_52c),blue); var hue; var _533; var _534=max; if(min==max){ hue=0; _533=0; }else{ var _535=(max-min); _533=_535/max; if(red==max){ hue=(_52c-blue)/_535; }else{ if(_52c==max){ hue=2+((blue-red)/_535); }else{ hue=4+((red-_52c)/_535); } } hue/=6; if(hue<0){ hue+=1; } if(hue>1){ hue-=1; } } return {h:hue,s:_533,v:_534,a:_52e}; },rgbToHSL:function(red,_537,blue,_539){ if(arguments.length==1){ var rgb=red; red=rgb.r; _537=rgb.g; blue=rgb.b; _539=rgb.a; } var max=Math.max(red,Math.max(_537,blue)); var min=Math.min(red,Math.min(_537,blue)); var hue; var _53e; var _53f=(max+min)/2; var _540=max-min; if(_540===0){ hue=0; _53e=0; }else{ if(_53f<=0.5){ _53e=_540/(max+min); }else{ _53e=_540/(2-max-min); } if(red==max){ hue=(_537-blue)/_540; }else{ if(_537==max){ hue=2+((blue-red)/_540); }else{ hue=4+((red-_537)/_540); } } hue/=6; if(hue<0){ hue+=1; } if(hue>1){ hue-=1; } } return {h:hue,s:_53e,l:_53f,a:_539}; },toColorPart:function(num){ num=Math.round(num); var _542=num.toString(16); if(num<16){ return "0"+_542; } return _542; },__new__:function(){ var m=MochiKit.Base; this.Color.fromRGBString=m.bind(this.Color._fromColorString,this.Color,"rgb","fromRGB",[1/255,1/255,1/255,1]); this.Color.fromHSLString=m.bind(this.Color._fromColorString,this.Color,"hsl","fromHSL",[1/360,0.01,0.01,1]); var _544=1/3; var _545={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_544,_544,_544],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_544,2*_544,2*_544],magenta:[1,0,1],orange:[1,0.5,0],purple:[0.5,0,0.5],red:[1,0,0],transparent:[0,0,0,0],white:[1,1,1],yellow:[1,1,0]}; var _546=function(name,r,g,b,a){ var rval=this.fromRGB(r,g,b,a); this[name]=function(){ return rval; }; return rval; }; for(var k in _545){ var name=k+"Color"; var _54f=m.concat([_546,this.Color,name],_545[k]); this.Color[name]=m.bind.apply(null,_54f); } var _550=function(){ for(var i=0;i1){ var src=MochiKit.DOM.getElement(arguments[0]); var sig=arguments[1]; var obj=arguments[2]; var func=arguments[3]; for(var i=_592.length-1;i>=0;i--){ var o=_592[i]; if(o.source===src&&o.signal===sig&&o.objOrFunc===obj&&o.funcOrStr===func){ self._disconnect(o); if(!self._lock){ _592.splice(i,1); }else{ self._dirty=true; } return true; } } }else{ var idx=m.findIdentical(_592,_590); if(idx>=0){ self._disconnect(_590); if(!self._lock){ _592.splice(idx,1); }else{ self._dirty=true; } return true; } } return false; },disconnectAllTo:function(_59b,_59c){ var self=MochiKit.Signal; var _59e=self._observers; var _59f=self._disconnect; var _5a0=self._lock; var _5a1=self._dirty; if(typeof (_59c)==="undefined"){ _59c=null; } for(var i=_59e.length-1;i>=0;i--){ var _5a3=_59e[i]; if(_5a3.objOrFunc===_59b&&(_59c===null||_5a3.funcOrStr===_59c)){ _59f(_5a3); if(_5a0){ _5a1=true; }else{ _59e.splice(i,1); } } } self._dirty=_5a1; },disconnectAll:function(src,sig){ src=MochiKit.DOM.getElement(src); var m=MochiKit.Base; var _5a7=m.flattenArguments(m.extend(null,arguments,1)); var self=MochiKit.Signal; var _5a9=self._disconnect; var _5aa=self._observers; var i,_5ac; var _5ad=self._lock; var _5ae=self._dirty; if(_5a7.length===0){ for(i=_5aa.length-1;i>=0;i--){ _5ac=_5aa[i]; if(_5ac.source===src){ _5a9(_5ac); if(!_5ad){ _5aa.splice(i,1); }else{ _5ae=true; } } } }else{ var sigs={}; for(i=0;i<_5a7.length;i++){ sigs[_5a7[i]]=true; } for(i=_5aa.length-1;i>=0;i--){ _5ac=_5aa[i]; if(_5ac.source===src&&_5ac.signal in sigs){ _5a9(_5ac); if(!_5ad){ _5aa.splice(i,1); }else{ _5ae=true; } } } } self._dirty=_5ae; },signal:function(src,sig){ var self=MochiKit.Signal; var _5b3=self._observers; src=MochiKit.DOM.getElement(src); var args=MochiKit.Base.extend(null,arguments,2); var _5b5=[]; self._lock=true; for(var i=0;i<_5b3.length;i++){ var _5b7=_5b3[i]; if(_5b7.source===src&&_5b7.signal===sig&&_5b7.connected){ try{ _5b7.listener.apply(src,args); } catch(e){ _5b5.push(e); } } } self._lock=false; if(self._dirty){ self._dirty=false; for(var i=_5b3.length-1;i>=0;i--){ if(!_5b3[i].connected){ _5b3.splice(i,1); } } } if(_5b5.length==1){ throw _5b5[0]; }else{ if(_5b5.length>1){ var e=new Error("Multiple errors thrown in handling 'sig', see errors property"); e.errors=_5b5; throw e; } } }}); MochiKit.Signal.EXPORT_OK=[]; MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll","disconnectAllTo"]; MochiKit.Signal.__new__=function(win){ var m=MochiKit.Base; this._document=document; this._window=win; this._lock=false; this._dirty=false; try{ this.connect(window,"onunload",this._unloadCache); } catch(e){ } this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; m.nameFunctions(this); }; MochiKit.Signal.__new__(this); if(MochiKit.__export__){ connect=MochiKit.Signal.connect; disconnect=MochiKit.Signal.disconnect; disconnectAll=MochiKit.Signal.disconnectAll; signal=MochiKit.Signal.signal; } MochiKit.Base._exportSymbols(this,MochiKit.Signal); MochiKit.Base._deps("Position",["Base","DOM","Style"]); MochiKit.Position.NAME="MochiKit.Position"; MochiKit.Position.VERSION="1.4.2"; MochiKit.Position.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Position.toString=function(){ return this.__repr__(); }; MochiKit.Position.EXPORT_OK=[]; MochiKit.Position.EXPORT=[]; MochiKit.Base.update(MochiKit.Position,{includeScrollOffsets:false,prepare:function(){ var _5bb=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0; var _5bc=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0; this.windowOffset=new MochiKit.Style.Coordinates(_5bb,_5bc); },cumulativeOffset:function(_5bd){ var _5be=0; var _5bf=0; do{ _5be+=_5bd.offsetTop||0; _5bf+=_5bd.offsetLeft||0; _5bd=_5bd.offsetParent; }while(_5bd); return new MochiKit.Style.Coordinates(_5bf,_5be); },realOffset:function(_5c0){ var _5c1=0; var _5c2=0; do{ _5c1+=_5c0.scrollTop||0; _5c2+=_5c0.scrollLeft||0; _5c0=_5c0.parentNode; }while(_5c0); return new MochiKit.Style.Coordinates(_5c2,_5c1); },within:function(_5c3,x,y){ if(this.includeScrollOffsets){ return this.withinIncludingScrolloffsets(_5c3,x,y); } this.xcomp=x; this.ycomp=y; this.offset=this.cumulativeOffset(_5c3); if(_5c3.style.position=="fixed"){ this.offset.x+=this.windowOffset.x; this.offset.y+=this.windowOffset.y; } return (y>=this.offset.y&&y=this.offset.x&&x=this.offset.y&&this.ycomp=this.offset.x&&this.xcomp"+el.innerHTML+"
"; },_roundTopCorners:function(el,_5f5,_5f6){ var _5f7=this._createCorner(_5f6); for(var i=0;i=0;i--){ _5fc.appendChild(this._createCornerSlice(_5fa,_5fb,i,"bottom")); } el.style.paddingBottom=0; el.appendChild(_5fc); },_createCorner:function(_5fe){ var dom=MochiKit.DOM; return dom.DIV({style:{backgroundColor:_5fe.toString()}}); },_createCornerSlice:function(_600,_601,n,_603){ var _604=MochiKit.DOM.SPAN(); var _605=_604.style; _605.backgroundColor=_600.toString(); _605.display="block"; _605.height="1px"; _605.overflow="hidden"; _605.fontSize="1px"; var _606=this._borderColor(_600,_601); if(this.options.border&&n===0){ _605.borderTopStyle="solid"; _605.borderTopWidth="1px"; _605.borderLeftWidth="0px"; _605.borderRightWidth="0px"; _605.borderBottomWidth="0px"; _605.height="0px"; _605.borderColor=_606.toString(); }else{ if(_606){ _605.borderColor=_606.toString(); _605.borderStyle="solid"; _605.borderWidth="0px 1px"; } } if(!this.options.compact&&(n==(this.options.numSlices-1))){ _605.height="2px"; } this._setMargin(_604,n,_603); this._setBorder(_604,n,_603); return _604; },_setOptions:function(_607){ this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false}; MochiKit.Base.update(this.options,_607); this.options.numSlices=(this.options.compact?2:4); },_whichSideTop:function(){ var _608=this.options.corners; if(this._hasString(_608,"all","top")){ return ""; } var _609=(_608.indexOf("tl")!=-1); var _60a=(_608.indexOf("tr")!=-1); if(_609&&_60a){ return ""; } if(_609){ return "left"; } if(_60a){ return "right"; } return ""; },_whichSideBottom:function(){ var _60b=this.options.corners; if(this._hasString(_60b,"all","bottom")){ return ""; } var _60c=(_60b.indexOf("bl")!=-1); var _60d=(_60b.indexOf("br")!=-1); if(_60c&&_60d){ return ""; } if(_60c){ return "left"; } if(_60d){ return "right"; } return ""; },_borderColor:function(_60e,_60f){ if(_60e=="transparent"){ return _60f; }else{ if(this.options.border){ return this.options.border; }else{ if(this.options.blend){ return _60f.blendedColor(_60e); } } } return ""; },_setMargin:function(el,n,_612){ var _613=this._marginSize(n)+"px"; var _614=(_612=="top"?this._whichSideTop():this._whichSideBottom()); var _615=el.style; if(_614=="left"){ _615.marginLeft=_613; _615.marginRight="0px"; }else{ if(_614=="right"){ _615.marginRight=_613; _615.marginLeft="0px"; }else{ _615.marginLeft=_613; _615.marginRight=_613; } } },_setBorder:function(el,n,_618){ var _619=this._borderSize(n)+"px"; var _61a=(_618=="top"?this._whichSideTop():this._whichSideBottom()); var _61b=el.style; if(_61a=="left"){ _61b.borderLeftWidth=_619; _61b.borderRightWidth="0px"; }else{ if(_61a=="right"){ _61b.borderRightWidth=_619; _61b.borderLeftWidth="0px"; }else{ _61b.borderLeftWidth=_619; _61b.borderRightWidth=_619; } } },_marginSize:function(n){ if(this.isTransparent){ return 0; } var o=this.options; if(o.compact&&o.blend){ var _61e=[1,0]; return _61e[n]; }else{ if(o.compact){ var _61f=[2,1]; return _61f[n]; }else{ if(o.blend){ var _620=[3,2,1,0]; return _620[n]; }else{ var _621=[5,3,2,1]; return _621[n]; } } } },_borderSize:function(n){ var o=this.options; var _624; if(o.compact&&(o.blend||this.isTransparent)){ return 1; }else{ if(o.compact){ _624=[1,0]; }else{ if(o.blend){ _624=[2,1,1,1]; }else{ if(o.border){ _624=[0,2,0,0]; }else{ if(this.isTransparent){ _624=[5,3,2,1]; }else{ return 0; } } } } } return _624[n]; },_hasString:function(str){ for(var i=1;i=(_651||i)){ _651=i; } },this.effects); _64d=_651||_64d; break; case "break": ma(function(e){ e.finalize(); },this.effects); break; } _64c.startOn+=_64d; _64c.finishOn+=_64d; if(!_64c.options.queue.limit||this.effects.length<_64c.options.queue.limit){ this.effects.push(_64c); } if(!this.interval){ this.interval=this.startLoop(MochiKit.Base.bind(this.loop,this),40); } },startLoop:function(func,_656){ return setInterval(func,_656); },remove:function(_657){ this.effects=MochiKit.Base.filter(function(e){ return e!=_657; },this.effects); if(!this.effects.length){ this.stopLoop(this.interval); this.interval=null; } },stopLoop:function(_659){ clearInterval(_659); },loop:function(){ var _65a=new Date().getTime(); MochiKit.Base.map(function(_65b){ _65b.loop(_65a); },this.effects); }}); MochiKit.Visual.Queues={instances:{},get:function(_65c){ if(typeof (_65c)!="string"){ return _65c; } if(!this.instances[_65c]){ this.instances[_65c]=new MochiKit.Visual.ScopedQueue(); } return this.instances[_65c]; }}; MochiKit.Visual.Queue=MochiKit.Visual.Queues.get("global"); MochiKit.Visual.DefaultOptions={transition:MochiKit.Visual.Transitions.sinoidal,duration:1,fps:25,sync:false,from:0,to:1,delay:0,queue:"parallel"}; MochiKit.Visual.Base=function(){ }; MochiKit.Visual.Base.prototype={__class__:MochiKit.Visual.Base,start:function(_65d){ var v=MochiKit.Visual; this.options=MochiKit.Base.setdefault(_65d,v.DefaultOptions); this.currentFrame=0; this.state="idle"; this.startOn=this.options.delay*1000; this.finishOn=this.startOn+(this.options.duration*1000); this.event("beforeStart"); if(!this.options.sync){ v.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).add(this); } },loop:function(_65f){ if(_65f>=this.startOn){ if(_65f>=this.finishOn){ return this.finalize(); } var pos=(_65f-this.startOn)/(this.finishOn-this.startOn); var _661=Math.round(pos*this.options.fps*this.options.duration); if(_661>this.currentFrame){ this.render(pos); this.currentFrame=_661; } } },render:function(pos){ if(this.state=="idle"){ this.state="running"; this.event("beforeSetup"); this.setup(); this.event("afterSetup"); } if(this.state=="running"){ if(this.options.transition){ pos=this.options.transition(pos); } pos*=(this.options.to-this.options.from); pos+=this.options.from; this.event("beforeUpdate"); this.update(pos); this.event("afterUpdate"); } },cancel:function(){ if(!this.options.sync){ MochiKit.Visual.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).remove(this); } this.state="finished"; },finalize:function(){ this.render(1); this.cancel(); this.event("beforeFinish"); this.finish(); this.event("afterFinish"); },setup:function(){ },finish:function(){ },update:function(_663){ },event:function(_664){ if(this.options[_664+"Internal"]){ this.options[_664+"Internal"](this); } if(this.options[_664]){ this.options[_664](this); } },repr:function(){ return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]"; }}; MochiKit.Visual.Parallel=function(_665,_666){ var cls=arguments.callee; if(!(this instanceof cls)){ return new cls(_665,_666); } this.__init__(_665,_666); }; MochiKit.Visual.Parallel.prototype=new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Parallel.prototype,{__class__:MochiKit.Visual.Parallel,__init__:function(_668,_669){ this.effects=_668||[]; this.start(_669); },update:function(_66a){ MochiKit.Base.map(function(_66b){ _66b.render(_66a); },this.effects); },finish:function(){ MochiKit.Base.map(function(_66c){ _66c.finalize(); },this.effects); }}); MochiKit.Visual.Sequence=function(_66d,_66e){ var cls=arguments.callee; if(!(this instanceof cls)){ return new cls(_66d,_66e); } this.__init__(_66d,_66e); }; MochiKit.Visual.Sequence.prototype=new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Sequence.prototype,{__class__:MochiKit.Visual.Sequence,__init__:function(_670,_671){ var defs={transition:MochiKit.Visual.Transitions.linear,duration:0}; this.effects=_670||[]; MochiKit.Base.map(function(_673){ defs.duration+=_673.options.duration; },this.effects); MochiKit.Base.setdefault(_671,defs); this.start(_671); },update:function(_674){ var time=_674*this.options.duration; for(var i=0;i0){ this.fontSize=parseFloat(_694); this.fontSizeType=_695; } },this),["em","px","%"]); this.factor=(this.options.scaleTo-this.options.scaleFrom)/100; if(/^content/.test(this.options.scaleMode)){ this.dims=[this.element.scrollHeight,this.element.scrollWidth]; }else{ if(this.options.scaleMode=="box"){ this.dims=[this.element.offsetHeight,this.element.offsetWidth]; }else{ this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth]; } } },update:function(_696){ var _697=(this.options.scaleFrom/100)+(this.factor*_696); if(this.options.scaleContent&&this.fontSize){ MochiKit.Style.setStyle(this.element,{fontSize:this.fontSize*_697+this.fontSizeType}); } this.setDimensions(this.dims[0]*_697,this.dims[1]*_697); },finish:function(){ if(this.restoreAfterFinish){ MochiKit.Style.setStyle(this.element,this.originalStyle); } },setDimensions:function(_698,_699){ var d={}; var r=Math.round; if(/MSIE/.test(navigator.userAgent)){ r=Math.ceil; } if(this.options.scaleX){ d.width=r(_699)+"px"; } if(this.options.scaleY){ d.height=r(_698)+"px"; } if(this.options.scaleFromCenter){ var topd=(_698-this.dims[0])/2; var _69d=(_699-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-_69d+"px"; } }else{ if(this.options.scaleY){ d.top=-topd+"px"; } if(this.options.scaleX){ d.left=-_69d+"px"; } } } MochiKit.Style.setStyle(this.element,d); }}); MochiKit.Visual.Highlight=function(_69e,_69f){ var cls=arguments.callee; if(!(this instanceof cls)){ return new cls(_69e,_69f); } this.__init__(_69e,_69f); }; MochiKit.Visual.Highlight.prototype=new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Highlight.prototype,{__class__:MochiKit.Visual.Highlight,__init__:function(_6a1,_6a2){ this.element=MochiKit.DOM.getElement(_6a1); _6a2=MochiKit.Base.update({startcolor:"#ffff99"},_6a2); this.start(_6a2); },setup:function(){ var b=MochiKit.Base; var s=MochiKit.Style; if(s.getStyle(this.element,"display")=="none"){ this.cancel(); return; } this.oldStyle={backgroundImage:s.getStyle(this.element,"background-image")}; s.setStyle(this.element,{backgroundImage:"none"}); if(!this.options.endcolor){ this.options.endcolor=MochiKit.Color.Color.fromBackground(this.element).toHexString(); } if(b.isUndefinedOrNull(this.options.restorecolor)){ this.options.restorecolor=s.getStyle(this.element,"background-color"); } this._base=b.map(b.bind(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16); },this),[0,1,2]); this._delta=b.map(b.bind(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i]; },this),[0,1,2]); },update:function(_6a7){ var m="#"; MochiKit.Base.map(MochiKit.Base.bind(function(i){ m+=MochiKit.Color.toColorPart(Math.round(this._base[i]+this._delta[i]*_6a7)); },this),[0,1,2]); MochiKit.Style.setStyle(this.element,{backgroundColor:m}); },finish:function(){ MochiKit.Style.setStyle(this.element,MochiKit.Base.update(this.oldStyle,{backgroundColor:this.options.restorecolor})); }}); MochiKit.Visual.ScrollTo=function(_6aa,_6ab){ var cls=arguments.callee; if(!(this instanceof cls)){ return new cls(_6aa,_6ab); } this.__init__(_6aa,_6ab); }; MochiKit.Visual.ScrollTo.prototype=new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype,{__class__:MochiKit.Visual.ScrollTo,__init__:function(_6ad,_6ae){ this.element=MochiKit.DOM.getElement(_6ad); this.start(_6ae); },setup:function(){ var p=MochiKit.Position; p.prepare(); var _6b0=p.cumulativeOffset(this.element); if(this.options.offset){ _6b0.y+=this.options.offset; } var max; if(window.innerHeight){ max=window.innerHeight-window.height; }else{ if(document.documentElement&&document.documentElement.clientHeight){ max=document.documentElement.clientHeight-document.body.scrollHeight; }else{ if(document.body){ max=document.body.clientHeight-document.body.scrollHeight; } } } this.scrollStart=p.windowOffset.y; this.delta=(_6b0.y>max?max:_6b0.y)-this.scrollStart; },update:function(_6b2){ var p=MochiKit.Position; p.prepare(); window.scrollTo(p.windowOffset.x,this.scrollStart+(_6b2*this.delta)); }}); MochiKit.Visual.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; MochiKit.Visual.Morph=function(_6b4,_6b5){ var cls=arguments.callee; if(!(this instanceof cls)){ return new cls(_6b4,_6b5); } this.__init__(_6b4,_6b5); }; MochiKit.Visual.Morph.prototype=new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Morph.prototype,{__class__:MochiKit.Visual.Morph,__init__:function(_6b7,_6b8){ this.element=MochiKit.DOM.getElement(_6b7); this.start(_6b8); },setup:function(){ var b=MochiKit.Base; var _6ba=this.options.style; this.styleStart={}; this.styleEnd={}; this.units={}; var _6bb,unit; for(var s in _6ba){ _6bb=_6ba[s]; s=b.camelize(s); if(MochiKit.Visual.CSS_LENGTH.test(_6bb)){ var _6be=_6bb.match(/^([\+\-]?[0-9\.]+)(.*)$/); _6bb=parseFloat(_6be[1]); unit=(_6be.length==3)?_6be[2]:null; this.styleEnd[s]=_6bb; this.units[s]=unit; _6bb=MochiKit.Style.getStyle(this.element,s); _6be=_6bb.match(/^([\+\-]?[0-9\.]+)(.*)$/); _6bb=parseFloat(_6be[1]); this.styleStart[s]=_6bb; }else{ if(/[Cc]olor$/.test(s)){ var c=MochiKit.Color.Color; _6bb=c.fromString(_6bb); if(_6bb){ this.units[s]="color"; this.styleEnd[s]=_6bb.toHexString(); _6bb=MochiKit.Style.getStyle(this.element,s); this.styleStart[s]=c.fromString(_6bb).toHexString(); this.styleStart[s]=b.map(b.bind(function(i){ return parseInt(this.styleStart[s].slice(i*2+1,i*2+3),16); },this),[0,1,2]); this.styleEnd[s]=b.map(b.bind(function(i){ return parseInt(this.styleEnd[s].slice(i*2+1,i*2+3),16); },this),[0,1,2]); } }else{ this.element.style[s]=_6bb; } } } },update:function(_6c2){ var _6c3; for(var s in this.styleStart){ if(this.units[s]=="color"){ var m="#"; var _6c6=this.styleStart[s]; var end=this.styleEnd[s]; MochiKit.Base.map(MochiKit.Base.bind(function(i){ m+=MochiKit.Color.toColorPart(Math.round(_6c6[i]+(end[i]-_6c6[i])*_6c2)); },this),[0,1,2]); this.element.style[s]=m; }else{ _6c3=this.styleStart[s]+Math.round((this.styleEnd[s]-this.styleStart[s])*_6c2*1000)/1000+this.units[s]; this.element.style[s]=_6c3; } } }}); MochiKit.Visual.fade=function(_6c9,_6ca){ var s=MochiKit.Style; var _6cc=s.getStyle(_6c9,"opacity"); _6ca=MochiKit.Base.update({from:s.getStyle(_6c9,"opacity")||1,to:0,afterFinishInternal:function(_6cd){ if(_6cd.options.to!==0){ return; } s.hideElement(_6cd.element); s.setStyle(_6cd.element,{"opacity":_6cc}); }},_6ca); return new MochiKit.Visual.Opacity(_6c9,_6ca); }; MochiKit.Visual.appear=function(_6ce,_6cf){ var s=MochiKit.Style; var v=MochiKit.Visual; _6cf=MochiKit.Base.update({from:(s.getStyle(_6ce,"display")=="none"?0:s.getStyle(_6ce,"opacity")||0),to:1,afterFinishInternal:function(_6d2){ v.forceRerendering(_6d2.element); },beforeSetupInternal:function(_6d3){ s.setStyle(_6d3.element,{"opacity":_6d3.options.from}); s.showElement(_6d3.element); }},_6cf); return new v.Opacity(_6ce,_6cf); }; MochiKit.Visual.puff=function(_6d4,_6d5){ var s=MochiKit.Style; var v=MochiKit.Visual; _6d4=MochiKit.DOM.getElement(_6d4); var _6d8=MochiKit.Style.getElementDimensions(_6d4,true); var _6d9={position:s.getStyle(_6d4,"position"),top:_6d4.style.top,left:_6d4.style.left,width:_6d4.style.width,height:_6d4.style.height,opacity:s.getStyle(_6d4,"opacity")}; _6d5=MochiKit.Base.update({beforeSetupInternal:function(_6da){ MochiKit.Position.absolutize(_6da.effects[0].element); },afterFinishInternal:function(_6db){ s.hideElement(_6db.effects[0].element); s.setStyle(_6db.effects[0].element,_6d9); },scaleContent:true,scaleFromCenter:true},_6d5); return new v.Parallel([new v.Scale(_6d4,200,{sync:true,scaleFromCenter:_6d5.scaleFromCenter,scaleMode:{originalHeight:_6d8.h,originalWidth:_6d8.w},scaleContent:_6d5.scaleContent,restoreAfterFinish:true}),new v.Opacity(_6d4,{sync:true,to:0})],_6d5); }; MochiKit.Visual.blindUp=function(_6dc,_6dd){ var d=MochiKit.DOM; var s=MochiKit.Style; _6dc=d.getElement(_6dc); var _6e0=s.getElementDimensions(_6dc,true); var _6e1=s.makeClipping(_6dc); _6dd=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleMode:{originalHeight:_6e0.h,originalWidth:_6e0.w},restoreAfterFinish:true,afterFinishInternal:function(_6e2){ s.hideElement(_6e2.element); s.undoClipping(_6e2.element,_6e1); }},_6dd); return new MochiKit.Visual.Scale(_6dc,0,_6dd); }; MochiKit.Visual.blindDown=function(_6e3,_6e4){ var d=MochiKit.DOM; var s=MochiKit.Style; _6e3=d.getElement(_6e3); var _6e7=s.getElementDimensions(_6e3,true); var _6e8; _6e4=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_6e7.h,originalWidth:_6e7.w},restoreAfterFinish:true,afterSetupInternal:function(_6e9){ _6e8=s.makeClipping(_6e9.element); s.setStyle(_6e9.element,{height:"0px"}); s.showElement(_6e9.element); },afterFinishInternal:function(_6ea){ s.undoClipping(_6ea.element,_6e8); }},_6e4); return new MochiKit.Visual.Scale(_6e3,100,_6e4); }; MochiKit.Visual.switchOff=function(_6eb,_6ec){ var d=MochiKit.DOM; var s=MochiKit.Style; _6eb=d.getElement(_6eb); var _6ef=s.getElementDimensions(_6eb,true); var _6f0=s.getStyle(_6eb,"opacity"); var _6f1; _6ec=MochiKit.Base.update({duration:0.7,restoreAfterFinish:true,beforeSetupInternal:function(_6f2){ s.makePositioned(_6eb); _6f1=s.makeClipping(_6eb); },afterFinishInternal:function(_6f3){ s.hideElement(_6eb); s.undoClipping(_6eb,_6f1); s.undoPositioned(_6eb); s.setStyle(_6eb,{"opacity":_6f0}); }},_6ec); var v=MochiKit.Visual; return new v.Sequence([new v.appear(_6eb,{sync:true,duration:0.57*_6ec.duration,from:0,transition:v.Transitions.flicker}),new v.Scale(_6eb,1,{sync:true,duration:0.43*_6ec.duration,scaleFromCenter:true,scaleX:false,scaleMode:{originalHeight:_6ef.h,originalWidth:_6ef.w},scaleContent:false,restoreAfterFinish:true})],_6ec); }; MochiKit.Visual.dropOut=function(_6f5,_6f6){ var d=MochiKit.DOM; var s=MochiKit.Style; _6f5=d.getElement(_6f5); var _6f9={top:s.getStyle(_6f5,"top"),left:s.getStyle(_6f5,"left"),opacity:s.getStyle(_6f5,"opacity")}; _6f6=MochiKit.Base.update({duration:0.5,distance:100,beforeSetupInternal:function(_6fa){ s.makePositioned(_6fa.effects[0].element); },afterFinishInternal:function(_6fb){ s.hideElement(_6fb.effects[0].element); s.undoPositioned(_6fb.effects[0].element); s.setStyle(_6fb.effects[0].element,_6f9); }},_6f6); var v=MochiKit.Visual; return new v.Parallel([new v.Move(_6f5,{x:0,y:_6f6.distance,sync:true}),new v.Opacity(_6f5,{sync:true,to:0})],_6f6); }; MochiKit.Visual.shake=function(_6fd,_6fe){ var d=MochiKit.DOM; var v=MochiKit.Visual; var s=MochiKit.Style; _6fd=d.getElement(_6fd); var _702={top:s.getStyle(_6fd,"top"),left:s.getStyle(_6fd,"left")}; _6fe=MochiKit.Base.update({duration:0.5,afterFinishInternal:function(_703){ s.undoPositioned(_6fd); s.setStyle(_6fd,_702); }},_6fe); return new v.Sequence([new v.Move(_6fd,{sync:true,duration:0.1*_6fe.duration,x:20,y:0}),new v.Move(_6fd,{sync:true,duration:0.2*_6fe.duration,x:-40,y:0}),new v.Move(_6fd,{sync:true,duration:0.2*_6fe.duration,x:40,y:0}),new v.Move(_6fd,{sync:true,duration:0.2*_6fe.duration,x:-40,y:0}),new v.Move(_6fd,{sync:true,duration:0.2*_6fe.duration,x:40,y:0}),new v.Move(_6fd,{sync:true,duration:0.1*_6fe.duration,x:-20,y:0})],_6fe); }; MochiKit.Visual.slideDown=function(_704,_705){ var d=MochiKit.DOM; var b=MochiKit.Base; var s=MochiKit.Style; _704=d.getElement(_704); if(!_704.firstChild){ throw new Error("MochiKit.Visual.slideDown must be used on a element with a child"); } d.removeEmptyTextNodes(_704); var _709=s.getStyle(_704.firstChild,"bottom")||0; var _70a=s.getElementDimensions(_704,true); var _70b; _705=b.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_70a.h,originalWidth:_70a.w},restoreAfterFinish:true,afterSetupInternal:function(_70c){ s.makePositioned(_70c.element); s.makePositioned(_70c.element.firstChild); if(/Opera/.test(navigator.userAgent)){ s.setStyle(_70c.element,{top:""}); } _70b=s.makeClipping(_70c.element); s.setStyle(_70c.element,{height:"0px"}); s.showElement(_70c.element); },afterUpdateInternal:function(_70d){ var _70e=s.getElementDimensions(_70d.element,true); s.setStyle(_70d.element.firstChild,{bottom:(_70d.dims[0]-_70e.h)+"px"}); },afterFinishInternal:function(_70f){ s.undoClipping(_70f.element,_70b); if(/MSIE/.test(navigator.userAgent)){ s.undoPositioned(_70f.element); s.undoPositioned(_70f.element.firstChild); }else{ s.undoPositioned(_70f.element.firstChild); s.undoPositioned(_70f.element); } s.setStyle(_70f.element.firstChild,{bottom:_709}); }},_705); return new MochiKit.Visual.Scale(_704,100,_705); }; MochiKit.Visual.slideUp=function(_710,_711){ var d=MochiKit.DOM; var b=MochiKit.Base; var s=MochiKit.Style; _710=d.getElement(_710); if(!_710.firstChild){ throw new Error("MochiKit.Visual.slideUp must be used on a element with a child"); } d.removeEmptyTextNodes(_710); var _715=s.getStyle(_710.firstChild,"bottom"); var _716=s.getElementDimensions(_710,true); var _717; _711=b.update({scaleContent:false,scaleX:false,scaleMode:{originalHeight:_716.h,originalWidth:_716.w},scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(_718){ s.makePositioned(_718.element); s.makePositioned(_718.element.firstChild); if(/Opera/.test(navigator.userAgent)){ s.setStyle(_718.element,{top:""}); } _717=s.makeClipping(_718.element); s.showElement(_718.element); },afterUpdateInternal:function(_719){ var _71a=s.getElementDimensions(_719.element,true); s.setStyle(_719.element.firstChild,{bottom:(_719.dims[0]-_71a.h)+"px"}); },afterFinishInternal:function(_71b){ s.hideElement(_71b.element); s.undoClipping(_71b.element,_717); s.undoPositioned(_71b.element.firstChild); s.undoPositioned(_71b.element); s.setStyle(_71b.element.firstChild,{bottom:_715}); }},_711); return new MochiKit.Visual.Scale(_710,0,_711); }; MochiKit.Visual.squish=function(_71c,_71d){ var d=MochiKit.DOM; var b=MochiKit.Base; var s=MochiKit.Style; var _721=s.getElementDimensions(_71c,true); var _722; _71d=b.update({restoreAfterFinish:true,scaleMode:{originalHeight:_721.w,originalWidth:_721.h},beforeSetupInternal:function(_723){ _722=s.makeClipping(_723.element); },afterFinishInternal:function(_724){ s.hideElement(_724.element); s.undoClipping(_724.element,_722); }},_71d); return new MochiKit.Visual.Scale(_71c,/Opera/.test(navigator.userAgent)?1:0,_71d); }; MochiKit.Visual.grow=function(_725,_726){ var d=MochiKit.DOM; var v=MochiKit.Visual; var s=MochiKit.Style; _725=d.getElement(_725); _726=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.full,scaleContent:true,scaleFromCenter:false},_726); var _72a={top:_725.style.top,left:_725.style.left,height:_725.style.height,width:_725.style.width,opacity:s.getStyle(_725,"opacity")}; var dims=s.getElementDimensions(_725,true); var _72c,_72d; var _72e,_72f; switch(_726.direction){ case "top-left": _72c=_72d=_72e=_72f=0; break; case "top-right": _72c=dims.w; _72d=_72f=0; _72e=-dims.w; break; case "bottom-left": _72c=_72e=0; _72d=dims.h; _72f=-dims.h; break; case "bottom-right": _72c=dims.w; _72d=dims.h; _72e=-dims.w; _72f=-dims.h; break; case "center": _72c=dims.w/2; _72d=dims.h/2; _72e=-dims.w/2; _72f=-dims.h/2; break; } var _730=MochiKit.Base.update({beforeSetupInternal:function(_731){ s.setStyle(_731.effects[0].element,{height:"0px"}); s.showElement(_731.effects[0].element); },afterFinishInternal:function(_732){ s.undoClipping(_732.effects[0].element); s.undoPositioned(_732.effects[0].element); s.setStyle(_732.effects[0].element,_72a); }},_726); return new v.Move(_725,{x:_72c,y:_72d,duration:0.01,beforeSetupInternal:function(_733){ s.hideElement(_733.element); s.makeClipping(_733.element); s.makePositioned(_733.element); },afterFinishInternal:function(_734){ new v.Parallel([new v.Opacity(_734.element,{sync:true,to:1,from:0,transition:_726.opacityTransition}),new v.Move(_734.element,{x:_72e,y:_72f,sync:true,transition:_726.moveTransition}),new v.Scale(_734.element,100,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,scaleFrom:/Opera/.test(navigator.userAgent)?1:0,transition:_726.scaleTransition,scaleContent:_726.scaleContent,scaleFromCenter:_726.scaleFromCenter,restoreAfterFinish:true})],_730); }}); }; MochiKit.Visual.shrink=function(_735,_736){ var d=MochiKit.DOM; var v=MochiKit.Visual; var s=MochiKit.Style; _735=d.getElement(_735); _736=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.none,scaleContent:true,scaleFromCenter:false},_736); var _73a={top:_735.style.top,left:_735.style.left,height:_735.style.height,width:_735.style.width,opacity:s.getStyle(_735,"opacity")}; var dims=s.getElementDimensions(_735,true); var _73c,_73d; switch(_736.direction){ case "top-left": _73c=_73d=0; break; case "top-right": _73c=dims.w; _73d=0; break; case "bottom-left": _73c=0; _73d=dims.h; break; case "bottom-right": _73c=dims.w; _73d=dims.h; break; case "center": _73c=dims.w/2; _73d=dims.h/2; break; } var _73e; var _73f=MochiKit.Base.update({beforeStartInternal:function(_740){ s.makePositioned(_740.effects[0].element); _73e=s.makeClipping(_740.effects[0].element); },afterFinishInternal:function(_741){ s.hideElement(_741.effects[0].element); s.undoClipping(_741.effects[0].element,_73e); s.undoPositioned(_741.effects[0].element); s.setStyle(_741.effects[0].element,_73a); }},_736); return new v.Parallel([new v.Opacity(_735,{sync:true,to:0,from:1,transition:_736.opacityTransition}),new v.Scale(_735,/Opera/.test(navigator.userAgent)?1:0,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,transition:_736.scaleTransition,scaleContent:_736.scaleContent,scaleFromCenter:_736.scaleFromCenter,restoreAfterFinish:true}),new v.Move(_735,{x:_73c,y:_73d,sync:true,transition:_736.moveTransition})],_73f); }; MochiKit.Visual.pulsate=function(_742,_743){ var d=MochiKit.DOM; var v=MochiKit.Visual; var b=MochiKit.Base; var _747=MochiKit.Style.getStyle(_742,"opacity"); _743=b.update({duration:3,from:0,afterFinishInternal:function(_748){ MochiKit.Style.setStyle(_748.element,{"opacity":_747}); }},_743); var _749=_743.transition||v.Transitions.sinoidal; _743.transition=function(pos){ return _749(1-v.Transitions.pulse(pos,_743.pulses)); }; return new v.Opacity(_742,_743); }; MochiKit.Visual.fold=function(_74b,_74c){ var d=MochiKit.DOM; var v=MochiKit.Visual; var s=MochiKit.Style; _74b=d.getElement(_74b); var _750=s.getElementDimensions(_74b,true); var _751={top:_74b.style.top,left:_74b.style.left,width:_74b.style.width,height:_74b.style.height}; var _752=s.makeClipping(_74b); _74c=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleMode:{originalHeight:_750.h,originalWidth:_750.w},afterFinishInternal:function(_753){ new v.Scale(_74b,1,{scaleContent:false,scaleY:false,scaleMode:{originalHeight:_750.h,originalWidth:_750.w},afterFinishInternal:function(_754){ s.hideElement(_754.element); s.undoClipping(_754.element,_752); s.setStyle(_754.element,_751); }}); }},_74c); return new v.Scale(_74b,5,_74c); }; MochiKit.Visual.Color=MochiKit.Color.Color; MochiKit.Visual.getElementsComputedStyle=MochiKit.DOM.computedStyle; MochiKit.Visual.__new__=function(){ var m=MochiKit.Base; m.nameFunctions(this); this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)}; }; MochiKit.Visual.EXPORT=["roundElement","roundClass","tagifyText","multiple","toggle","Parallel","Sequence","Opacity","Move","Scale","Highlight","ScrollTo","Morph","fade","appear","puff","blindUp","blindDown","switchOff","dropOut","shake","slideDown","slideUp","squish","grow","shrink","pulsate","fold"]; MochiKit.Visual.EXPORT_OK=["Base","PAIRS"]; MochiKit.Visual.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.Visual); MochiKit.Base._deps("DragAndDrop",["Base","Iter","DOM","Signal","Visual","Position"]); MochiKit.DragAndDrop.NAME="MochiKit.DragAndDrop"; MochiKit.DragAndDrop.VERSION="1.4.2"; MochiKit.DragAndDrop.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.DragAndDrop.toString=function(){ return this.__repr__(); }; MochiKit.DragAndDrop.EXPORT=["Droppable","Draggable"]; MochiKit.DragAndDrop.EXPORT_OK=["Droppables","Draggables"]; MochiKit.DragAndDrop.Droppables={drops:[],remove:function(_756){ this.drops=MochiKit.Base.filter(function(d){ return d.element!=MochiKit.DOM.getElement(_756); },this.drops); },register:function(drop){ this.drops.push(drop); },unregister:function(drop){ this.drops=MochiKit.Base.filter(function(d){ return d!=drop; },this.drops); },prepare:function(_75b){ MochiKit.Base.map(function(drop){ if(drop.isAccepted(_75b)){ if(drop.options.activeclass){ MochiKit.DOM.addElementClass(drop.element,drop.options.activeclass); } drop.options.onactive(drop.element,_75b); } },this.drops); },findDeepestChild:function(_75d){ deepest=_75d[0]; for(i=1;i<_75d.length;++i){ if(MochiKit.DOM.isChildNode(_75d[i].element,deepest.element)){ deepest=_75d[i]; } } return deepest; },show:function(_75e,_75f){ if(!this.drops.length){ return; } var _760=[]; if(this.last_active){ this.last_active.deactivate(); } MochiKit.Iter.forEach(this.drops,function(drop){ if(drop.isAffected(_75e,_75f)){ _760.push(drop); } }); if(_760.length>0){ drop=this.findDeepestChild(_760); MochiKit.Position.within(drop.element,_75e.page.x,_75e.page.y); drop.options.onhover(_75f,drop.element,MochiKit.Position.overlap(drop.options.overlap,drop.element)); drop.activate(); } },fire:function(_762,_763){ if(!this.last_active){ return; } MochiKit.Position.prepare(); if(this.last_active.isAffected(_762.mouse(),_763)){ this.last_active.options.ondrop(_763,this.last_active.element,_762); } },reset:function(_764){ MochiKit.Base.map(function(drop){ if(drop.options.activeclass){ MochiKit.DOM.removeElementClass(drop.element,drop.options.activeclass); } drop.options.ondesactive(drop.element,_764); },this.drops); if(this.last_active){ this.last_active.deactivate(); } }}; MochiKit.DragAndDrop.Droppable=function(_766,_767){ var cls=arguments.callee; if(!(this instanceof cls)){ return new cls(_766,_767); } this.__init__(_766,_767); }; MochiKit.DragAndDrop.Droppable.prototype={__class__:MochiKit.DragAndDrop.Droppable,__init__:function(_769,_76a){ var d=MochiKit.DOM; var b=MochiKit.Base; this.element=d.getElement(_769); this.options=b.update({greedy:true,hoverclass:null,activeclass:null,hoverfunc:b.noop,accept:null,onactive:b.noop,ondesactive:b.noop,onhover:b.noop,ondrop:b.noop,containment:[],tree:false},_76a); this.options._containers=[]; b.map(MochiKit.Base.bind(function(c){ this.options._containers.push(d.getElement(c)); },this),this.options.containment); MochiKit.Style.makePositioned(this.element); MochiKit.DragAndDrop.Droppables.register(this); },isContained:function(_76e){ if(this.options._containers.length){ var _76f; if(this.options.tree){ _76f=_76e.treeNode; }else{ _76f=_76e.parentNode; } return MochiKit.Iter.some(this.options._containers,function(c){ return _76f==c; }); }else{ return true; } },isAccepted:function(_771){ return ((!this.options.accept)||MochiKit.Iter.some(this.options.accept,function(c){ return MochiKit.DOM.hasElementClass(_771,c); })); },isAffected:function(_773,_774){ return ((this.element!=_774)&&this.isContained(_774)&&this.isAccepted(_774)&&MochiKit.Position.within(this.element,_773.page.x,_773.page.y)); },deactivate:function(){ if(this.options.hoverclass){ MochiKit.DOM.removeElementClass(this.element,this.options.hoverclass); } this.options.hoverfunc(this.element,false); MochiKit.DragAndDrop.Droppables.last_active=null; },activate:function(){ if(this.options.hoverclass){ MochiKit.DOM.addElementClass(this.element,this.options.hoverclass); } this.options.hoverfunc(this.element,true); MochiKit.DragAndDrop.Droppables.last_active=this; },destroy:function(){ MochiKit.DragAndDrop.Droppables.unregister(this); },repr:function(){ return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]"; }}; MochiKit.DragAndDrop.Draggables={drags:[],register:function(_775){ if(this.drags.length===0){ var conn=MochiKit.Signal.connect; this.eventMouseUp=conn(document,"onmouseup",this,this.endDrag); this.eventMouseMove=conn(document,"onmousemove",this,this.updateDrag); this.eventKeypress=conn(document,"onkeypress",this,this.keyPress); } this.drags.push(_775); },unregister:function(_777){ this.drags=MochiKit.Base.filter(function(d){ return d!=_777; },this.drags); if(this.drags.length===0){ var disc=MochiKit.Signal.disconnect; disc(this.eventMouseUp); disc(this.eventMouseMove); disc(this.eventKeypress); } },activate:function(_77a){ window.focus(); this.activeDraggable=_77a; },deactivate:function(){ this.activeDraggable=null; },updateDrag:function(_77b){ if(!this.activeDraggable){ return; } var _77c=_77b.mouse(); if(this._lastPointer&&(MochiKit.Base.repr(this._lastPointer.page)==MochiKit.Base.repr(_77c.page))){ return; } this._lastPointer=_77c; this.activeDraggable.updateDrag(_77b,_77c); },endDrag:function(_77d){ if(!this.activeDraggable){ return; } this._lastPointer=null; this.activeDraggable.endDrag(_77d); this.activeDraggable=null; },keyPress:function(_77e){ if(this.activeDraggable){ this.activeDraggable.keyPress(_77e); } },notify:function(_77f,_780,_781){ MochiKit.Signal.signal(this,_77f,_780,_781); }}; MochiKit.DragAndDrop.Draggable=function(_782,_783){ var cls=arguments.callee; if(!(this instanceof cls)){ return new cls(_782,_783); } this.__init__(_782,_783); }; MochiKit.DragAndDrop.Draggable.prototype={__class__:MochiKit.DragAndDrop.Draggable,__init__:function(_785,_786){ var v=MochiKit.Visual; var b=MochiKit.Base; _786=b.update({handle:false,starteffect:function(_789){ this._savedOpacity=MochiKit.Style.getStyle(_789,"opacity")||1; new v.Opacity(_789,{duration:0.2,from:this._savedOpacity,to:0.7}); },reverteffect:function(_78a,_78b,_78c){ var dur=Math.sqrt(Math.abs(_78b^2)+Math.abs(_78c^2))*0.02; return new v.Move(_78a,{x:-_78c,y:-_78b,duration:dur}); },endeffect:function(_78e){ new v.Opacity(_78e,{duration:0.2,from:0.7,to:this._savedOpacity}); },onchange:b.noop,zindex:1000,revert:false,scroll:false,scrollSensitivity:20,scrollSpeed:15,snap:false},_786); var d=MochiKit.DOM; this.element=d.getElement(_785); if(_786.handle&&(typeof (_786.handle)=="string")){ this.handle=d.getFirstElementByTagAndClassName(null,_786.handle,this.element); } if(!this.handle){ this.handle=d.getElement(_786.handle); } if(!this.handle){ this.handle=this.element; } if(_786.scroll&&!_786.scroll.scrollTo&&!_786.scroll.outerHTML){ _786.scroll=d.getElement(_786.scroll); this._isScrollChild=MochiKit.DOM.isChildNode(this.element,_786.scroll); } MochiKit.Style.makePositioned(this.element); this.delta=this.currentDelta(); this.options=_786; this.dragging=false; this.eventMouseDown=MochiKit.Signal.connect(this.handle,"onmousedown",this,this.initDrag); MochiKit.DragAndDrop.Draggables.register(this); },destroy:function(){ MochiKit.Signal.disconnect(this.eventMouseDown); MochiKit.DragAndDrop.Draggables.unregister(this); },currentDelta:function(){ var s=MochiKit.Style.getStyle; return [parseInt(s(this.element,"left")||"0"),parseInt(s(this.element,"top")||"0")]; },initDrag:function(_791){ if(!_791.mouse().button.left){ return; } var src=_791.target(); var _793=(src.tagName||"").toUpperCase(); if(_793==="INPUT"||_793==="SELECT"||_793==="OPTION"||_793==="BUTTON"||_793==="TEXTAREA"){ return; } if(this._revert){ this._revert.cancel(); this._revert=null; } var _794=_791.mouse(); var pos=MochiKit.Position.cumulativeOffset(this.element); this.offset=[_794.page.x-pos.x,_794.page.y-pos.y]; MochiKit.DragAndDrop.Draggables.activate(this); _791.stop(); },startDrag:function(_796){ this.dragging=true; if(this.options.selectclass){ MochiKit.DOM.addElementClass(this.element,this.options.selectclass); } if(this.options.zindex){ this.originalZ=parseInt(MochiKit.Style.getStyle(this.element,"z-index")||"0"); this.element.style.zIndex=this.options.zindex; } if(this.options.ghosting){ this._clone=this.element.cloneNode(true); this.ghostPosition=MochiKit.Position.absolutize(this.element); this.element.parentNode.insertBefore(this._clone,this.element); } if(this.options.scroll){ if(this.options.scroll==window){ var _797=this._getWindowScroll(this.options.scroll); this.originalScrollLeft=_797.left; this.originalScrollTop=_797.top; }else{ this.originalScrollLeft=this.options.scroll.scrollLeft; this.originalScrollTop=this.options.scroll.scrollTop; } } MochiKit.DragAndDrop.Droppables.prepare(this.element); MochiKit.DragAndDrop.Draggables.notify("start",this,_796); if(this.options.starteffect){ this.options.starteffect(this.element); } },updateDrag:function(_798,_799){ if(!this.dragging){ this.startDrag(_798); } MochiKit.Position.prepare(); MochiKit.DragAndDrop.Droppables.show(_799,this.element); MochiKit.DragAndDrop.Draggables.notify("drag",this,_798); this.draw(_799); this.options.onchange(this); if(this.options.scroll){ this.stopScrolling(); var p,q; if(this.options.scroll==window){ var s=this._getWindowScroll(this.options.scroll); p=new MochiKit.Style.Coordinates(s.left,s.top); q=new MochiKit.Style.Coordinates(s.left+s.width,s.top+s.height); }else{ p=MochiKit.Position.page(this.options.scroll); p.x+=this.options.scroll.scrollLeft; p.y+=this.options.scroll.scrollTop; p.x+=(window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0); p.y+=(window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0); q=new MochiKit.Style.Coordinates(p.x+this.options.scroll.offsetWidth,p.y+this.options.scroll.offsetHeight); } var _79d=[0,0]; if(_799.page.x>(q.x-this.options.scrollSensitivity)){ _79d[0]=_799.page.x-(q.x-this.options.scrollSensitivity); }else{ if(_799.page.x<(p.x+this.options.scrollSensitivity)){ _79d[0]=_799.page.x-(p.x+this.options.scrollSensitivity); } } if(_799.page.y>(q.y-this.options.scrollSensitivity)){ _79d[1]=_799.page.y-(q.y-this.options.scrollSensitivity); }else{ if(_799.page.y<(p.y+this.options.scrollSensitivity)){ _79d[1]=_799.page.y-(p.y+this.options.scrollSensitivity); } } this.startScrolling(_79d); } if(/AppleWebKit/.test(navigator.appVersion)){ window.scrollBy(0,0); } _798.stop(); },finishDrag:function(_79e,_79f){ var dr=MochiKit.DragAndDrop; this.dragging=false; if(this.options.selectclass){ MochiKit.DOM.removeElementClass(this.element,this.options.selectclass); } if(this.options.ghosting){ MochiKit.Position.relativize(this.element,this.ghostPosition); MochiKit.DOM.removeElement(this._clone); this._clone=null; } if(_79f){ dr.Droppables.fire(_79e,this.element); } dr.Draggables.notify("end",this,_79e); var _7a1=this.options.revert; if(_7a1&&typeof (_7a1)=="function"){ _7a1=_7a1(this.element); } var d=this.currentDelta(); if(_7a1&&this.options.reverteffect){ this._revert=this.options.reverteffect(this.element,d[1]-this.delta[1],d[0]-this.delta[0]); }else{ this.delta=d; } if(this.options.zindex){ this.element.style.zIndex=this.originalZ; } if(this.options.endeffect){ this.options.endeffect(this.element); } dr.Draggables.deactivate(); dr.Droppables.reset(this.element); },keyPress:function(_7a3){ if(_7a3.key().string!="KEY_ESCAPE"){ return; } this.finishDrag(_7a3,false); _7a3.stop(); },endDrag:function(_7a4){ if(!this.dragging){ return; } this.stopScrolling(); this.finishDrag(_7a4,true); _7a4.stop(); },draw:function(_7a5){ var pos=MochiKit.Position.cumulativeOffset(this.element); var d=this.currentDelta(); pos.x-=d[0]; pos.y-=d[1]; if(this.options.scroll&&(this.options.scroll!=window&&this._isScrollChild)){ pos.x-=this.options.scroll.scrollLeft-this.originalScrollLeft; pos.y-=this.options.scroll.scrollTop-this.originalScrollTop; } var p=[_7a5.page.x-pos.x-this.offset[0],_7a5.page.y-pos.y-this.offset[1]]; if(this.options.snap){ if(typeof (this.options.snap)=="function"){ p=this.options.snap(p[0],p[1]); }else{ if(this.options.snap instanceof Array){ var i=-1; p=MochiKit.Base.map(MochiKit.Base.bind(function(v){ i+=1; return Math.round(v/this.options.snap[i])*this.options.snap[i]; },this),p); }else{ p=MochiKit.Base.map(MochiKit.Base.bind(function(v){ return Math.round(v/this.options.snap)*this.options.snap; },this),p); } } } var _7ac=this.element.style; if((!this.options.constraint)||(this.options.constraint=="horizontal")){ _7ac.left=p[0]+"px"; } if((!this.options.constraint)||(this.options.constraint=="vertical")){ _7ac.top=p[1]+"px"; } if(_7ac.visibility=="hidden"){ _7ac.visibility=""; } },stopScrolling:function(){ if(this.scrollInterval){ clearInterval(this.scrollInterval); this.scrollInterval=null; MochiKit.DragAndDrop.Draggables._lastScrollPointer=null; } },startScrolling:function(_7ad){ if(!_7ad[0]&&!_7ad[1]){ return; } this.scrollSpeed=[_7ad[0]*this.options.scrollSpeed,_7ad[1]*this.options.scrollSpeed]; this.lastScrolled=new Date(); this.scrollInterval=setInterval(MochiKit.Base.bind(this.scroll,this),10); },scroll:function(){ var _7ae=new Date(); var _7af=_7ae-this.lastScrolled; this.lastScrolled=_7ae; if(this.options.scroll==window){ var s=this._getWindowScroll(this.options.scroll); if(this.scrollSpeed[0]||this.scrollSpeed[1]){ var dm=_7af/1000; this.options.scroll.scrollTo(s.left+dm*this.scrollSpeed[0],s.top+dm*this.scrollSpeed[1]); } }else{ this.options.scroll.scrollLeft+=this.scrollSpeed[0]*_7af/1000; this.options.scroll.scrollTop+=this.scrollSpeed[1]*_7af/1000; } var d=MochiKit.DragAndDrop; MochiKit.Position.prepare(); d.Droppables.show(d.Draggables._lastPointer,this.element); d.Draggables.notify("drag",this); if(this._isScrollChild){ d.Draggables._lastScrollPointer=d.Draggables._lastScrollPointer||d.Draggables._lastPointer; d.Draggables._lastScrollPointer.x+=this.scrollSpeed[0]*_7af/1000; d.Draggables._lastScrollPointer.y+=this.scrollSpeed[1]*_7af/1000; if(d.Draggables._lastScrollPointer.x<0){ d.Draggables._lastScrollPointer.x=0; } if(d.Draggables._lastScrollPointer.y<0){ d.Draggables._lastScrollPointer.y=0; } this.draw(d.Draggables._lastScrollPointer); } this.options.onchange(this); },_getWindowScroll:function(win){ var vp,w,h; MochiKit.DOM.withWindow(win,function(){ vp=MochiKit.Style.getViewportPosition(win.document); }); if(win.innerWidth){ w=win.innerWidth; h=win.innerHeight; }else{ if(win.document.documentElement&&win.document.documentElement.clientWidth){ w=win.document.documentElement.clientWidth; h=win.document.documentElement.clientHeight; }else{ w=win.document.body.offsetWidth; h=win.document.body.offsetHeight; } } return {top:vp.y,left:vp.x,width:w,height:h}; },repr:function(){ return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]"; }}; MochiKit.DragAndDrop.__new__=function(){ MochiKit.Base.nameFunctions(this); this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)}; }; MochiKit.DragAndDrop.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.DragAndDrop); MochiKit.Base._deps("Sortable",["Base","Iter","DOM","Position","DragAndDrop"]); MochiKit.Sortable.NAME="MochiKit.Sortable"; MochiKit.Sortable.VERSION="1.4.2"; MochiKit.Sortable.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.Sortable.toString=function(){ return this.__repr__(); }; MochiKit.Sortable.EXPORT=[]; MochiKit.Sortable.EXPORT_OK=[]; MochiKit.Base.update(MochiKit.Sortable,{sortables:{},_findRootElement:function(_7b7){ while(_7b7.tagName.toUpperCase()!="BODY"){ if(_7b7.id&&MochiKit.Sortable.sortables[_7b7.id]){ return _7b7; } _7b7=_7b7.parentNode; } },_createElementId:function(_7b8){ if(_7b8.id==null||_7b8.id==""){ var d=MochiKit.DOM; var id; var _7bb=1; while(d.getElement(id="sortable"+_7bb)!=null){ _7bb+=1; } d.setNodeAttribute(_7b8,"id",id); } },options:function(_7bc){ _7bc=MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(_7bc)); if(!_7bc){ return; } return MochiKit.Sortable.sortables[_7bc.id]; },destroy:function(_7bd){ var s=MochiKit.Sortable.options(_7bd); var b=MochiKit.Base; var d=MochiKit.DragAndDrop; if(s){ MochiKit.Signal.disconnect(s.startHandle); MochiKit.Signal.disconnect(s.endHandle); b.map(function(dr){ d.Droppables.remove(dr); },s.droppables); b.map(function(dr){ dr.destroy(); },s.draggables); delete MochiKit.Sortable.sortables[s.element.id]; } },create:function(_7c3,_7c4){ _7c3=MochiKit.DOM.getElement(_7c3); var self=MochiKit.Sortable; self._createElementId(_7c3); _7c4=MochiKit.Base.update({element:_7c3,tag:"li",dropOnEmpty:false,tree:false,treeTag:"ul",overlap:"vertical",constraint:"vertical",containment:[_7c3],handle:false,only:false,hoverclass:null,ghosting:false,scroll:false,scrollSensitivity:20,scrollSpeed:15,format:/^[^_]*_(.*)$/,onChange:MochiKit.Base.noop,onUpdate:MochiKit.Base.noop,accept:null},_7c4); self.destroy(_7c3); var _7c6={revert:true,ghosting:_7c4.ghosting,scroll:_7c4.scroll,scrollSensitivity:_7c4.scrollSensitivity,scrollSpeed:_7c4.scrollSpeed,constraint:_7c4.constraint,handle:_7c4.handle}; if(_7c4.starteffect){ _7c6.starteffect=_7c4.starteffect; } if(_7c4.reverteffect){ _7c6.reverteffect=_7c4.reverteffect; }else{ if(_7c4.ghosting){ _7c6.reverteffect=function(_7c7){ _7c7.style.top=0; _7c7.style.left=0; }; } } if(_7c4.endeffect){ _7c6.endeffect=_7c4.endeffect; } if(_7c4.zindex){ _7c6.zindex=_7c4.zindex; } var _7c8={overlap:_7c4.overlap,containment:_7c4.containment,hoverclass:_7c4.hoverclass,onhover:self.onHover,tree:_7c4.tree,accept:_7c4.accept}; var _7c9={onhover:self.onEmptyHover,overlap:_7c4.overlap,containment:_7c4.containment,hoverclass:_7c4.hoverclass,accept:_7c4.accept}; MochiKit.DOM.removeEmptyTextNodes(_7c3); _7c4.draggables=[]; _7c4.droppables=[]; if(_7c4.dropOnEmpty||_7c4.tree){ new MochiKit.DragAndDrop.Droppable(_7c3,_7c9); _7c4.droppables.push(_7c3); } MochiKit.Base.map(function(e){ var _7cb=_7c4.handle?MochiKit.DOM.getFirstElementByTagAndClassName(null,_7c4.handle,e):e; _7c4.draggables.push(new MochiKit.DragAndDrop.Draggable(e,MochiKit.Base.update(_7c6,{handle:_7cb}))); new MochiKit.DragAndDrop.Droppable(e,_7c8); if(_7c4.tree){ e.treeNode=_7c3; } _7c4.droppables.push(e); },(self.findElements(_7c3,_7c4)||[])); if(_7c4.tree){ MochiKit.Base.map(function(e){ new MochiKit.DragAndDrop.Droppable(e,_7c9); e.treeNode=_7c3; _7c4.droppables.push(e); },(self.findTreeElements(_7c3,_7c4)||[])); } self.sortables[_7c3.id]=_7c4; _7c4.lastValue=self.serialize(_7c3); _7c4.startHandle=MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables,"start",MochiKit.Base.partial(self.onStart,_7c3)); _7c4.endHandle=MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables,"end",MochiKit.Base.partial(self.onEnd,_7c3)); },onStart:function(_7cd,_7ce){ var self=MochiKit.Sortable; var _7d0=self.options(_7cd); _7d0.lastValue=self.serialize(_7d0.element); },onEnd:function(_7d1,_7d2){ var self=MochiKit.Sortable; self.unmark(); var _7d4=self.options(_7d1); if(_7d4.lastValue!=self.serialize(_7d4.element)){ _7d4.onUpdate(_7d4.element); } },findElements:function(_7d5,_7d6){ return MochiKit.Sortable.findChildren(_7d5,_7d6.only,_7d6.tree,_7d6.tag); },findTreeElements:function(_7d7,_7d8){ return MochiKit.Sortable.findChildren(_7d7,_7d8.only,_7d8.tree?true:false,_7d8.treeTag); },findChildren:function(_7d9,only,_7db,_7dc){ if(!_7d9.hasChildNodes()){ return null; } _7dc=_7dc.toUpperCase(); if(only){ only=MochiKit.Base.flattenArray([only]); } var _7dd=[]; MochiKit.Base.map(function(e){ if(e.tagName&&e.tagName.toUpperCase()==_7dc&&(!only||MochiKit.Iter.some(only,function(c){ return MochiKit.DOM.hasElementClass(e,c); }))){ _7dd.push(e); } if(_7db){ var _7e0=MochiKit.Sortable.findChildren(e,only,_7db,_7dc); if(_7e0&&_7e0.length>0){ _7dd=_7dd.concat(_7e0); } } },_7d9.childNodes); return _7dd; },onHover:function(_7e1,_7e2,_7e3){ if(MochiKit.DOM.isChildNode(_7e2,_7e1)){ return; } var self=MochiKit.Sortable; if(_7e3>0.33&&_7e3<0.66&&self.options(_7e2).tree){ return; }else{ if(_7e3>0.5){ self.mark(_7e2,"before"); if(_7e2.previousSibling!=_7e1){ var _7e5=_7e1.parentNode; _7e1.style.visibility="hidden"; _7e2.parentNode.insertBefore(_7e1,_7e2); if(_7e2.parentNode!=_7e5){ self.options(_7e5).onChange(_7e1); } self.options(_7e2.parentNode).onChange(_7e1); } }else{ self.mark(_7e2,"after"); var _7e6=_7e2.nextSibling||null; if(_7e6!=_7e1){ var _7e5=_7e1.parentNode; _7e1.style.visibility="hidden"; _7e2.parentNode.insertBefore(_7e1,_7e6); if(_7e2.parentNode!=_7e5){ self.options(_7e5).onChange(_7e1); } self.options(_7e2.parentNode).onChange(_7e1); } } } },_offsetSize:function(_7e7,type){ if(type=="vertical"||type=="height"){ return _7e7.offsetHeight; }else{ return _7e7.offsetWidth; } },onEmptyHover:function(_7e9,_7ea,_7eb){ var _7ec=_7e9.parentNode; var self=MochiKit.Sortable; var _7ee=self.options(_7ea); if(!MochiKit.DOM.isChildNode(_7ea,_7e9)){ var _7ef; var _7f0=self.findElements(_7ea,{tag:_7ee.tag,only:_7ee.only}); var _7f1=null; if(_7f0){ var _7f2=self._offsetSize(_7ea,_7ee.overlap)*(1-_7eb); for(_7ef=0;_7ef<_7f0.length;_7ef+=1){ if(_7f2-self._offsetSize(_7f0[_7ef],_7ee.overlap)>=0){ _7f2-=self._offsetSize(_7f0[_7ef],_7ee.overlap); }else{ if(_7f2-(self._offsetSize(_7f0[_7ef],_7ee.overlap)/2)>=0){ _7f1=_7ef+1<_7f0.length?_7f0[_7ef+1]:null; break; }else{ _7f1=_7f0[_7ef]; break; } } } } _7ea.insertBefore(_7e9,_7f1); self.options(_7ec).onChange(_7e9); _7ee.onChange(_7e9); } },unmark:function(){ var m=MochiKit.Sortable._marker; if(m){ MochiKit.Style.hideElement(m); } },mark:function(_7f4,_7f5){ var d=MochiKit.DOM; var self=MochiKit.Sortable; var _7f8=self.options(_7f4.parentNode); if(_7f8&&!_7f8.ghosting){ return; } if(!self._marker){ self._marker=d.getElement("dropmarker")||document.createElement("DIV"); MochiKit.Style.hideElement(self._marker); d.addElementClass(self._marker,"dropmarker"); self._marker.style.position="absolute"; document.getElementsByTagName("body").item(0).appendChild(self._marker); } var _7f9=MochiKit.Position.cumulativeOffset(_7f4); self._marker.style.left=_7f9.x+"px"; self._marker.style.top=_7f9.y+"px"; if(_7f5=="after"){ if(_7f8.overlap=="horizontal"){ self._marker.style.left=(_7f9.x+_7f4.clientWidth)+"px"; }else{ self._marker.style.top=(_7f9.y+_7f4.clientHeight)+"px"; } } MochiKit.Style.showElement(self._marker); },_tree:function(_7fa,_7fb,_7fc){ var self=MochiKit.Sortable; var _7fe=self.findElements(_7fa,_7fb)||[]; for(var i=0;i<_7fe.length;++i){ var _800=_7fe[i].id.match(_7fb.format); if(!_800){ continue; } var _801={id:encodeURIComponent(_800?_800[1]:null),element:_7fa,parent:_7fc,children:[],position:_7fc.children.length,container:self._findChildrenElement(_7fe[i],_7fb.treeTag.toUpperCase())}; if(_801.container){ self._tree(_801.container,_7fb,_801); } _7fc.children.push(_801); } return _7fc; },_findChildrenElement:function(_802,_803){ if(_802&&_802.hasChildNodes){ _803=_803.toUpperCase(); for(var i=0;i<_802.childNodes.length;++i){ if(_802.childNodes[i].tagName.toUpperCase()==_803){ return _802.childNodes[i]; } } } return null; },tree:function(_805,_806){ _805=MochiKit.DOM.getElement(_805); var _807=MochiKit.Sortable.options(_805); _806=MochiKit.Base.update({tag:_807.tag,treeTag:_807.treeTag,only:_807.only,name:_805.id,format:_807.format},_806||{}); var root={id:null,parent:null,children:new Array,container:_805,position:0}; return MochiKit.Sortable._tree(_805,_806,root); },setSequence:function(_809,_80a,_80b){ var self=MochiKit.Sortable; var b=MochiKit.Base; _809=MochiKit.DOM.getElement(_809); _80b=b.update(self.options(_809),_80b||{}); var _80e={}; b.map(function(n){ var m=n.id.match(_80b.format); if(m){ _80e[m[1]]=[n,n.parentNode]; } n.parentNode.removeChild(n); },self.findElements(_809,_80b)); b.map(function(_811){ var n=_80e[_811]; if(n){ n[1].appendChild(n[0]); delete _80e[_811]; } },_80a); },_constructIndex:function(node){ var _814=""; do{ if(node.id){ _814="["+node.position+"]"+_814; } }while((node=node.parent)!=null); return _814; },sequence:function(_815,_816){ _815=MochiKit.DOM.getElement(_815); var self=MochiKit.Sortable; var _816=MochiKit.Base.update(self.options(_815),_816||{}); return MochiKit.Base.map(function(item){ return item.id.match(_816.format)?item.id.match(_816.format)[1]:""; },MochiKit.DOM.getElement(self.findElements(_815,_816)||[])); },serialize:function(_819,_81a){ _819=MochiKit.DOM.getElement(_819); var self=MochiKit.Sortable; _81a=MochiKit.Base.update(self.options(_819),_81a||{}); var name=encodeURIComponent(_81a.name||_819.id); if(_81a.tree){ return MochiKit.Base.flattenArray(MochiKit.Base.map(function(item){ return [name+self._constructIndex(item)+"[id]="+encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); },self.tree(_819,_81a).children)).join("&"); }else{ return MochiKit.Base.map(function(item){ return name+"[]="+encodeURIComponent(item); },self.sequence(_819,_81a)).join("&"); } }}); MochiKit.Sortable.Sortable=MochiKit.Sortable; MochiKit.Sortable.__new__=function(){ MochiKit.Base.nameFunctions(this); this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)}; }; MochiKit.Sortable.__new__(); MochiKit.Base._exportSymbols(this,MochiKit.Sortable); if(typeof (MochiKit)=="undefined"){ MochiKit={}; } if(typeof (MochiKit.MochiKit)=="undefined"){ MochiKit.MochiKit={}; } MochiKit.MochiKit.NAME="MochiKit.MochiKit"; MochiKit.MochiKit.VERSION="1.4.2"; MochiKit.MochiKit.__repr__=function(){ return "["+this.NAME+" "+this.VERSION+"]"; }; MochiKit.MochiKit.toString=function(){ return this.__repr__(); }; MochiKit.MochiKit.SUBMODULES=["Base","Iter","Logging","DateTime","Format","Async","DOM","Selector","Style","LoggingPane","Color","Signal","Position","Visual","DragAndDrop","Sortable"]; if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){ if(typeof (dojo)!="undefined"){ dojo.provide("MochiKit.MochiKit"); (function(lst){ for(var i=0;i"); } } })(); } MochiKit-1.4.2/MANIFEST0000660000175000017500000001314011113647642013432 0ustar scottscottChanges META.json MANIFEST This list of files LICENSE.txt doc/html/MochiKit/Async.html doc/html/MochiKit/Base.html doc/html/MochiKit/Color.html doc/html/MochiKit/DateTime.html doc/html/MochiKit/DOM.html doc/html/MochiKit/DragAndDrop.html doc/html/MochiKit/Format.html doc/html/MochiKit/index.html doc/html/MochiKit/Iter.html doc/html/MochiKit/Logging.html doc/html/MochiKit/LoggingPane.html doc/html/MochiKit/Position.html doc/html/MochiKit/Selector.html doc/html/MochiKit/Signal.html doc/html/MochiKit/Sortable.html doc/html/MochiKit/Style.html doc/html/MochiKit/VersionHistory.html doc/html/MochiKit/Visual.html doc/js/toc.js doc/rst/MochiKit/Async.rst doc/rst/MochiKit/Base.rst doc/rst/MochiKit/Color.rst doc/rst/MochiKit/DateTime.rst doc/rst/MochiKit/DOM.rst doc/rst/MochiKit/DragAndDrop.rst doc/rst/MochiKit/Format.rst doc/rst/MochiKit/index.rst doc/rst/MochiKit/Iter.rst doc/rst/MochiKit/Logging.rst doc/rst/MochiKit/LoggingPane.rst doc/rst/MochiKit/Position.rst doc/rst/MochiKit/Selector.rst doc/rst/MochiKit/Signal.rst doc/rst/MochiKit/Sortable.rst doc/rst/MochiKit/Style.rst doc/rst/MochiKit/VersionHistory.rst doc/rst/MochiKit/Visual.rst examples/ajax_tables/ajax_tables.css examples/ajax_tables/ajax_tables.js examples/ajax_tables/domains.json examples/ajax_tables/domains.xml examples/ajax_tables/index.html examples/color_wheel/color_wheel.css examples/color_wheel/color_wheel.js examples/color_wheel/index.html examples/dnd_sortable/dnd_sortable.css examples/dnd_sortable/dropmarker.png examples/dnd_sortable/icon.png examples/dnd_sortable/index.html examples/dnd_sortable/sortable2_test.html examples/dnd_sortable/sortable3_test.html examples/dnd_sortable/sortable4_test.html examples/dnd_sortable/sortable5_test.html examples/dnd_sortable/sortable_test.html examples/dnd_sortable/sortable_tree_test.html examples/draggable/draggable.css examples/draggable/draggable.js examples/draggable/index.html examples/effects/effects_bigslide.html examples/effects/effects_blind.html examples/effects/effects_blindslide.html examples/effects/effects_combi.css examples/effects/effects_fadeappear.html examples/effects/effects_grow_shrink.html examples/effects/effects_onload.html examples/effects/effects_queue.html examples/effects/effects_queue_limit.html examples/effects/effects_scroll.html examples/effects/effects_slide.html examples/effects/full.html examples/effects/icon.png examples/effects/index.html examples/interpreter/index.html examples/interpreter/interpreter.css examples/interpreter/interpreter.js examples/key_events/index.html examples/key_events/key_events.css examples/key_events/key_events.js examples/logging_pane/index.html examples/logging_pane/logging_pane.css examples/logging_pane/logging_pane.js examples/mochiregexp/index.html examples/mochiregexp/mochiregexp.css examples/mochiregexp/mochiregexp.js examples/mouse_events/index.html examples/mouse_events/mouse_events.css examples/mouse_events/mouse_events.js examples/rounded_corners/index.html examples/rounded_corners/rounded_corners.css examples/rounded_corners/rounded_corners.js examples/simple_dnd/dnd_boxes.html examples/simple_dnd/dnd_full.html examples/simple_dnd/dnd_ghost.html examples/simple_dnd/dnd_hoverclass.html examples/simple_dnd/dnd_scroll.html examples/simple_dnd/dnd_snap.html examples/simple_dnd/index.html examples/simple_dnd/simple_dnd.css examples/sortable_tables/index.html examples/sortable_tables/sortable_tables.css examples/sortable_tables/sortable_tables.js examples/view-source/view-source.css examples/view-source/view-source.html examples/view-source/view-source.js examples/view-source/lib/SyntaxHighlighter/shBrushCSharp.js examples/view-source/lib/SyntaxHighlighter/shBrushDelphi.js examples/view-source/lib/SyntaxHighlighter/shBrushJScript.js examples/view-source/lib/SyntaxHighlighter/shBrushPhp.js examples/view-source/lib/SyntaxHighlighter/shBrushPython.js examples/view-source/lib/SyntaxHighlighter/shBrushSql.js examples/view-source/lib/SyntaxHighlighter/shBrushVb.js examples/view-source/lib/SyntaxHighlighter/shBrushXml.js examples/view-source/lib/SyntaxHighlighter/shCore.js examples/view-source/lib/SyntaxHighlighter/SyntaxHighlighter.css examples/view-source/lib/SyntaxHighlighter/Tests.html include/_img/bg_docheader.gif include/_img/g_bullet.gif include/_img/g_logo_doc.gif include/css/documentation.css include/css/general.css MochiKit/__package__.js MochiKit/Async.js MochiKit/Base.js MochiKit/Color.js MochiKit/DateTime.js MochiKit/DOM.js MochiKit/DragAndDrop.js MochiKit/Format.js MochiKit/Iter.js MochiKit/Logging.js MochiKit/LoggingPane.js MochiKit/MochiKit.js MochiKit/MockDOM.js MochiKit/Position.js MochiKit/Selector.js MochiKit/Signal.js MochiKit/Sortable.js MochiKit/Style.js MochiKit/Test.js MochiKit/Visual.js packed/MochiKit/__package__.js packed/MochiKit/customize.html packed/MochiKit/MochiKit.js tests/cli.js tests/FakeJSAN.js tests/index.html tests/standalone.js tests/test_Base.js tests/test_Color.js tests/test_DateTime.js tests/test_DragAndDrop.js tests/test_Format.js tests/test_Iter.js tests/test_Logging.js tests/test_MochiKit-Async.html tests/test_MochiKit-Async.json tests/test_MochiKit-Base.html tests/test_MochiKit-Color.html tests/test_MochiKit-DateTime.html tests/test_MochiKit-DOM-Safari.html tests/test_MochiKit-DOM.html tests/test_MochiKit-DragAndDrop.html tests/test_MochiKit-Format.html tests/test_MochiKit-Iter.html tests/test_MochiKit-JSAN.html tests/test_MochiKit-Logging.html tests/test_MochiKit-MochiKit.html tests/test_MochiKit-Selector.html tests/test_MochiKit-Signal.html tests/test_MochiKit-Style.html tests/test_MochiKit-Visual.html tests/test_Signal.js tests/SimpleTest/SimpleTest.js tests/SimpleTest/test.css tests/SimpleTest/TestRunner.js MochiKit-1.4.2/lib/0000755000175000017500000000000011136470265013052 5ustar scottscottMochiKit-1.4.2/lib/MochiKit/0000755000175000017500000000000011136470265014561 5ustar scottscottMochiKit-1.4.2/lib/MochiKit/Selector.js0000660000175000017500000003615311110666336016703 0ustar scottscott/*** MochiKit.Selector 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito and others. All rights Reserved. ***/ MochiKit.Base._deps('Selector', ['Base', 'DOM', 'Iter']); MochiKit.Selector.NAME = "MochiKit.Selector"; MochiKit.Selector.VERSION = "1.4.2"; MochiKit.Selector.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.Selector.toString = function () { return this.__repr__(); }; MochiKit.Selector.EXPORT = [ "Selector", "findChildElements", "findDocElements", "$$" ]; MochiKit.Selector.EXPORT_OK = [ ]; MochiKit.Selector.Selector = function (expression) { this.params = {classNames: [], pseudoClassNames: []}; this.expression = expression.toString().replace(/(^\s+|\s+$)/g, ''); this.parseExpression(); this.compileMatcher(); }; MochiKit.Selector.Selector.prototype = { /*** Selector class: convenient object to make CSS selections. ***/ __class__: MochiKit.Selector.Selector, /** @id MochiKit.Selector.Selector.prototype.parseExpression */ parseExpression: function () { function abort(message) { throw 'Parse error in selector: ' + message; } if (this.expression == '') { abort('empty expression'); } var repr = MochiKit.Base.repr; var params = this.params; var expr = this.expression; var 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 ':': params.pseudoClassNames.push(clause); break; case '': case undefined: params.tagName = clause.toUpperCase(); break; default: abort(repr(expr)); } expr = rest; } if (expr.length > 0) { abort(repr(expr)); } }, /** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */ buildMatchExpression: function () { var repr = MochiKit.Base.repr; var params = this.params; var conditions = []; var clause, i; function childElements(element) { return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)"; } if (params.wildcard) { conditions.push('true'); } if (clause = params.id) { conditions.push('element.id == ' + repr(clause)); } if (clause = params.tagName) { conditions.push('element.tagName.toUpperCase() == ' + repr(clause)); } if ((clause = params.classNames).length > 0) { for (i = 0; i < clause.length; i++) { conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')'); } } if ((clause = params.pseudoClassNames).length > 0) { for (i = 0; i < clause.length; i++) { var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/); var pseudoClass = match[1]; var pseudoClassArgument = match[2]; switch (pseudoClass) { case 'root': conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break; case 'nth-child': case 'nth-last-child': case 'nth-of-type': case 'nth-last-of-type': match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/); if (!match) { throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument; } var a, b; if (match[0] == 'odd') { a = 2; b = 1; } else if (match[0] == 'even') { a = 2; b = 0; } else { a = match[2] && parseInt(match) || null; b = parseInt(match[3]); } conditions.push('this.nthChild(element,' + a + ',' + b + ',' + !!pseudoClass.match('^nth-last') // Reverse + ',' + !!pseudoClass.match('of-type$') // Restrict to same tagName + ')'); break; case 'first-child': conditions.push('this.nthChild(element, null, 1)'); break; case 'last-child': conditions.push('this.nthChild(element, null, 1, true)'); break; case 'first-of-type': conditions.push('this.nthChild(element, null, 1, false, true)'); break; case 'last-of-type': conditions.push('this.nthChild(element, null, 1, true, true)'); break; case 'only-child': conditions.push(childElements('element.parentNode') + '.length == 1'); break; case 'only-of-type': conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1'); break; case 'empty': conditions.push('element.childNodes.length == 0'); break; case 'enabled': conditions.push('(this.isUIElement(element) && element.disabled === false)'); break; case 'disabled': conditions.push('(this.isUIElement(element) && element.disabled === true)'); break; case 'checked': conditions.push('(this.isUIElement(element) && element.checked === true)'); break; case 'not': var subselector = new MochiKit.Selector.Selector(pseudoClassArgument); conditions.push('!( ' + subselector.buildMatchExpression() + ')') break; } } } if (clause = params.attributes) { MochiKit.Base.map(function (attribute) { var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')'; var splitValueBy = function (delimiter) { return value + '.split(' + repr(delimiter) + ')'; } conditions.push(value + ' != null'); switch (attribute.operator) { case '=': conditions.push(value + ' == ' + repr(attribute.value)); break; case '~=': conditions.push('MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1'); break; case '^=': conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value)); break; case '$=': conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value)); break; case '*=': conditions.push(value + '.match(' + repr(attribute.value) + ')'); break; case '|=': conditions.push(splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase())); break; case '!=': conditions.push(value + ' != ' + repr(attribute.value)); break; case '': case undefined: // Condition already added above break; default: throw 'Unknown operator ' + attribute.operator + ' in selector'; } }, clause); } return conditions.join(' && '); }, /** @id MochiKit.Selector.Selector.prototype.compileMatcher */ compileMatcher: function () { var code = 'return (!element.tagName) ? false : ' + this.buildMatchExpression() + ';'; this.match = new Function('element', code); }, /** @id MochiKit.Selector.Selector.prototype.nthChild */ nthChild: function (element, a, b, reverse, sametag){ var siblings = MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, element.parentNode.childNodes); if (sametag) { siblings = MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, siblings); } if (reverse) { siblings = MochiKit.Iter.reversed(siblings); } if (a) { var actualIndex = MochiKit.Base.findIdentical(siblings, element); return ((actualIndex + 1 - b) / a) % 1 == 0; } else { return b == MochiKit.Base.findIdentical(siblings, element) + 1; } }, /** @id MochiKit.Selector.Selector.prototype.isUIElement */ isUIElement: function (element) { return MochiKit.Base.findValue(['input', 'button', 'select', 'option', 'textarea', 'object'], element.tagName.toLowerCase()) > -1; }, /** @id MochiKit.Selector.Selector.prototype.findElements */ findElements: function (scope, axis) { var element; if (axis == undefined) { axis = ""; } function inScope(element, scope) { if (axis == "") { return MochiKit.DOM.isChildNode(element, scope); } else if (axis == ">") { return element.parentNode === scope; } else if (axis == "+") { return element === nextSiblingElement(scope); } else if (axis == "~") { var sibling = scope; while (sibling = nextSiblingElement(sibling)) { if (element === sibling) { return true; } } return false; } else { throw "Invalid axis: " + axis; } } if (element = MochiKit.DOM.getElement(this.params.id)) { if (this.match(element)) { if (!scope || inScope(element, scope)) { return [element]; } } } function nextSiblingElement(node) { node = node.nextSibling; while (node && node.nodeType != 1) { node = node.nextSibling; } return node; } if (axis == "") { scope = (scope || MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName || '*'); } else if (axis == ">") { if (!scope) { throw "> combinator not allowed without preceeding expression"; } scope = MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, scope.childNodes); } else if (axis == "+") { if (!scope) { throw "+ combinator not allowed without preceeding expression"; } scope = nextSiblingElement(scope) && [nextSiblingElement(scope)]; } else if (axis == "~") { if (!scope) { throw "~ combinator not allowed without preceeding expression"; } var newscope = []; while (nextSiblingElement(scope)) { scope = nextSiblingElement(scope); newscope.push(scope); } scope = newscope; } if (!scope) { return []; } var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) { return this.match(scopeElt); }, this), scope); return results; }, /** @id MochiKit.Selector.Selector.prototype.repr */ repr: function () { return 'Selector(' + this.expression + ')'; }, toString: MochiKit.Base.forwardCall("repr") }; MochiKit.Base.update(MochiKit.Selector, { /** @id MochiKit.Selector.findChildElements */ findChildElements: function (element, expressions) { var uniq = function(arr) { var res = []; for (var i = 0; i < arr.length; i++) { if (MochiKit.Base.findIdentical(res, arr[i]) < 0) { res.push(arr[i]); } } return res; }; return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) { var nextScope = ""; var reducer = function (results, expr) { if (match = expr.match(/^[>+~]$/)) { nextScope = match[0]; return results; } else { var selector = new MochiKit.Selector.Selector(expr); var elements = MochiKit.Iter.reduce(function (elements, result) { return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope)); }, results, []); nextScope = ""; return elements; } }; var exprs = expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/); return uniq(MochiKit.Iter.reduce(reducer, exprs, [null])); }, expressions)); }, findDocElements: function () { return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments); }, __new__: function () { var m = MochiKit.Base; this.$$ = this.findDocElements; this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); } }); MochiKit.Selector.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.Selector); MochiKit-1.4.2/lib/MochiKit/Base.js0000660000175000017500000012713011110670162015761 0ustar scottscott/*** MochiKit.Base 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ if (typeof(dojo) != 'undefined') { dojo.provide("MochiKit.Base"); } if (typeof(MochiKit) == 'undefined') { MochiKit = {}; } if (typeof(MochiKit.Base) == 'undefined') { MochiKit.Base = {}; } if (typeof(MochiKit.__export__) == "undefined") { MochiKit.__export__ = (MochiKit.__compat__ || (typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined') ); } MochiKit.Base.VERSION = "1.4.2"; MochiKit.Base.NAME = "MochiKit.Base"; /** @id MochiKit.Base.update */ MochiKit.Base.update = function (self, obj/*, ... */) { if (self === null || self === undefined) { self = {}; } for (var i = 1; i < arguments.length; i++) { var o = arguments[i]; if (typeof(o) != 'undefined' && o !== null) { for (var k in o) { self[k] = o[k]; } } } return self; }; MochiKit.Base.update(MochiKit.Base, { __repr__: function () { return "[" + this.NAME + " " + this.VERSION + "]"; }, toString: function () { return this.__repr__(); }, /** @id MochiKit.Base.camelize */ camelize: function (selector) { /* from dojo.style.toCamelCase */ var arr = selector.split('-'); var cc = arr[0]; for (var i = 1; i < arr.length; i++) { cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1); } return cc; }, /** @id MochiKit.Base.counter */ counter: function (n/* = 1 */) { if (arguments.length === 0) { n = 1; } return function () { return n++; }; }, /** @id MochiKit.Base.clone */ clone: function (obj) { var me = arguments.callee; if (arguments.length == 1) { me.prototype = obj; return new me(); } }, _deps: function(module, deps) { if (!(module in MochiKit)) { MochiKit[module] = {}; } if (typeof(dojo) != 'undefined') { dojo.provide('MochiKit.' + module); } for (var i = 0; i < deps.length; i++) { if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.' + deps[i]); } if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.' + deps[i], []); } if (!(deps[i] in MochiKit)) { throw 'MochiKit.' + module + ' depends on MochiKit.' + deps[i] + '!' } } }, _flattenArray: function (res, lst) { for (var i = 0; i < lst.length; i++) { var o = lst[i]; if (o instanceof Array) { arguments.callee(res, o); } else { res.push(o); } } return res; }, /** @id MochiKit.Base.flattenArray */ flattenArray: function (lst) { return MochiKit.Base._flattenArray([], lst); }, /** @id MochiKit.Base.flattenArguments */ flattenArguments: function (lst/* ...*/) { var res = []; var m = MochiKit.Base; var args = m.extend(null, arguments); while (args.length) { var o = args.shift(); if (o && typeof(o) == "object" && typeof(o.length) == "number") { for (var i = o.length - 1; i >= 0; i--) { args.unshift(o[i]); } } else { res.push(o); } } return res; }, /** @id MochiKit.Base.extend */ extend: function (self, obj, /* optional */skip) { // Extend an array with an array-like object starting // from the skip index if (!skip) { skip = 0; } if (obj) { // allow iterable fall-through, but skip the full isArrayLike // check for speed, this is called often. var l = obj.length; if (typeof(l) != 'number' /* !isArrayLike(obj) */) { if (typeof(MochiKit.Iter) != "undefined") { obj = MochiKit.Iter.list(obj); l = obj.length; } else { throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); } } if (!self) { self = []; } for (var i = skip; i < l; i++) { self.push(obj[i]); } } // This mutates, but it's convenient to return because // it's often used like a constructor when turning some // ghetto array-like to a real array return self; }, /** @id MochiKit.Base.updatetree */ updatetree: function (self, obj/*, ...*/) { if (self === null || self === undefined) { self = {}; } for (var i = 1; i < arguments.length; i++) { var o = arguments[i]; if (typeof(o) != 'undefined' && o !== null) { for (var k in o) { var v = o[k]; if (typeof(self[k]) == 'object' && typeof(v) == 'object') { arguments.callee(self[k], v); } else { self[k] = v; } } } } return self; }, /** @id MochiKit.Base.setdefault */ setdefault: function (self, obj/*, ...*/) { if (self === null || self === undefined) { self = {}; } for (var i = 1; i < arguments.length; i++) { var o = arguments[i]; for (var k in o) { if (!(k in self)) { self[k] = o[k]; } } } return self; }, /** @id MochiKit.Base.keys */ keys: function (obj) { var rval = []; for (var prop in obj) { rval.push(prop); } return rval; }, /** @id MochiKit.Base.values */ values: function (obj) { var rval = []; for (var prop in obj) { rval.push(obj[prop]); } return rval; }, /** @id MochiKit.Base.items */ items: function (obj) { var rval = []; var e; for (var prop in obj) { var v; try { v = obj[prop]; } catch (e) { continue; } rval.push([prop, v]); } return rval; }, _newNamedError: function (module, name, func) { func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name); module[name] = func; }, /** @id MochiKit.Base.operator */ operator: { // unary logic operators /** @id MochiKit.Base.truth */ truth: function (a) { return !!a; }, /** @id MochiKit.Base.lognot */ lognot: function (a) { return !a; }, /** @id MochiKit.Base.identity */ identity: function (a) { return a; }, // bitwise unary operators /** @id MochiKit.Base.not */ not: function (a) { return ~a; }, /** @id MochiKit.Base.neg */ neg: function (a) { return -a; }, // binary operators /** @id MochiKit.Base.add */ add: function (a, b) { return a + b; }, /** @id MochiKit.Base.sub */ sub: function (a, b) { return a - b; }, /** @id MochiKit.Base.div */ div: function (a, b) { return a / b; }, /** @id MochiKit.Base.mod */ mod: function (a, b) { return a % b; }, /** @id MochiKit.Base.mul */ mul: function (a, b) { return a * b; }, // bitwise binary operators /** @id MochiKit.Base.and */ and: function (a, b) { return a & b; }, /** @id MochiKit.Base.or */ or: function (a, b) { return a | b; }, /** @id MochiKit.Base.xor */ xor: function (a, b) { return a ^ b; }, /** @id MochiKit.Base.lshift */ lshift: function (a, b) { return a << b; }, /** @id MochiKit.Base.rshift */ rshift: function (a, b) { return a >> b; }, /** @id MochiKit.Base.zrshift */ zrshift: function (a, b) { return a >>> b; }, // near-worthless built-in comparators /** @id MochiKit.Base.eq */ eq: function (a, b) { return a == b; }, /** @id MochiKit.Base.ne */ ne: function (a, b) { return a != b; }, /** @id MochiKit.Base.gt */ gt: function (a, b) { return a > b; }, /** @id MochiKit.Base.ge */ ge: function (a, b) { return a >= b; }, /** @id MochiKit.Base.lt */ lt: function (a, b) { return a < b; }, /** @id MochiKit.Base.le */ le: function (a, b) { return a <= b; }, // strict built-in comparators seq: function (a, b) { return a === b; }, sne: function (a, b) { return a !== b; }, // compare comparators /** @id MochiKit.Base.ceq */ ceq: function (a, b) { return MochiKit.Base.compare(a, b) === 0; }, /** @id MochiKit.Base.cne */ cne: function (a, b) { return MochiKit.Base.compare(a, b) !== 0; }, /** @id MochiKit.Base.cgt */ cgt: function (a, b) { return MochiKit.Base.compare(a, b) == 1; }, /** @id MochiKit.Base.cge */ cge: function (a, b) { return MochiKit.Base.compare(a, b) != -1; }, /** @id MochiKit.Base.clt */ clt: function (a, b) { return MochiKit.Base.compare(a, b) == -1; }, /** @id MochiKit.Base.cle */ cle: function (a, b) { return MochiKit.Base.compare(a, b) != 1; }, // binary logical operators /** @id MochiKit.Base.logand */ logand: function (a, b) { return a && b; }, /** @id MochiKit.Base.logor */ logor: function (a, b) { return a || b; }, /** @id MochiKit.Base.contains */ contains: function (a, b) { return b in a; } }, /** @id MochiKit.Base.forwardCall */ forwardCall: function (func) { return function () { return this[func].apply(this, arguments); }; }, /** @id MochiKit.Base.itemgetter */ itemgetter: function (func) { return function (arg) { return arg[func]; }; }, /** @id MochiKit.Base.typeMatcher */ typeMatcher: function (/* typ */) { var types = {}; for (var i = 0; i < arguments.length; i++) { var typ = arguments[i]; types[typ] = typ; } return function () { for (var i = 0; i < arguments.length; i++) { if (!(typeof(arguments[i]) in types)) { return false; } } return true; }; }, /** @id MochiKit.Base.isNull */ isNull: function (/* ... */) { for (var i = 0; i < arguments.length; i++) { if (arguments[i] !== null) { return false; } } return true; }, /** @id MochiKit.Base.isUndefinedOrNull */ isUndefinedOrNull: function (/* ... */) { for (var i = 0; i < arguments.length; i++) { var o = arguments[i]; if (!(typeof(o) == 'undefined' || o === null)) { return false; } } return true; }, /** @id MochiKit.Base.isEmpty */ isEmpty: function (obj) { return !MochiKit.Base.isNotEmpty.apply(this, arguments); }, /** @id MochiKit.Base.isNotEmpty */ isNotEmpty: function (obj) { for (var i = 0; i < arguments.length; i++) { var o = arguments[i]; if (!(o && o.length)) { return false; } } return true; }, /** @id MochiKit.Base.isArrayLike */ isArrayLike: function () { for (var i = 0; i < arguments.length; i++) { var o = arguments[i]; var typ = typeof(o); if ( (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) || o === null || typeof(o.length) != 'number' || o.nodeType === 3 || o.nodeType === 4 ) { return false; } } return true; }, /** @id MochiKit.Base.isDateLike */ isDateLike: function () { for (var i = 0; i < arguments.length; i++) { var o = arguments[i]; if (typeof(o) != "object" || o === null || typeof(o.getTime) != 'function') { return false; } } return true; }, /** @id MochiKit.Base.xmap */ xmap: function (fn/*, obj... */) { if (fn === null) { return MochiKit.Base.extend(null, arguments, 1); } var rval = []; for (var i = 1; i < arguments.length; i++) { rval.push(fn(arguments[i])); } return rval; }, /** @id MochiKit.Base.map */ map: function (fn, lst/*, lst... */) { var m = MochiKit.Base; var itr = MochiKit.Iter; var isArrayLike = m.isArrayLike; if (arguments.length <= 2) { // allow an iterable to be passed if (!isArrayLike(lst)) { if (itr) { // fast path for map(null, iterable) lst = itr.list(lst); if (fn === null) { return lst; } } else { throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); } } // fast path for map(null, lst) if (fn === null) { return m.extend(null, lst); } // disabled fast path for map(fn, lst) /* if (false && typeof(Array.prototype.map) == 'function') { // Mozilla fast-path return Array.prototype.map.call(lst, fn); } */ var rval = []; for (var i = 0; i < lst.length; i++) { rval.push(fn(lst[i])); } return rval; } else { // default for map(null, ...) is zip(...) if (fn === null) { fn = Array; } var length = null; for (i = 1; i < arguments.length; i++) { // allow iterables to be passed if (!isArrayLike(arguments[i])) { if (itr) { return itr.list(itr.imap.apply(null, arguments)); } else { throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); } } // find the minimum length var l = arguments[i].length; if (length === null || length > l) { length = l; } } rval = []; for (i = 0; i < length; i++) { var args = []; for (var j = 1; j < arguments.length; j++) { args.push(arguments[j][i]); } rval.push(fn.apply(this, args)); } return rval; } }, /** @id MochiKit.Base.xfilter */ xfilter: function (fn/*, obj... */) { var rval = []; if (fn === null) { fn = MochiKit.Base.operator.truth; } for (var i = 1; i < arguments.length; i++) { var o = arguments[i]; if (fn(o)) { rval.push(o); } } return rval; }, /** @id MochiKit.Base.filter */ filter: function (fn, lst, self) { var rval = []; // allow an iterable to be passed var m = MochiKit.Base; if (!m.isArrayLike(lst)) { if (MochiKit.Iter) { lst = MochiKit.Iter.list(lst); } else { throw new TypeError("Argument not an array-like and MochiKit.Iter not present"); } } if (fn === null) { fn = m.operator.truth; } if (typeof(Array.prototype.filter) == 'function') { // Mozilla fast-path return Array.prototype.filter.call(lst, fn, self); } else if (typeof(self) == 'undefined' || self === null) { for (var i = 0; i < lst.length; i++) { var o = lst[i]; if (fn(o)) { rval.push(o); } } } else { for (i = 0; i < lst.length; i++) { o = lst[i]; if (fn.call(self, o)) { rval.push(o); } } } return rval; }, _wrapDumbFunction: function (func) { return function () { // fast path! switch (arguments.length) { case 0: return func(); case 1: return func(arguments[0]); case 2: return func(arguments[0], arguments[1]); case 3: return func(arguments[0], arguments[1], arguments[2]); } var args = []; for (var i = 0; i < arguments.length; i++) { args.push("arguments[" + i + "]"); } return eval("(func(" + args.join(",") + "))"); }; }, /** @id MochiKit.Base.methodcaller */ methodcaller: function (func/*, args... */) { var args = MochiKit.Base.extend(null, arguments, 1); if (typeof(func) == "function") { return function (obj) { return func.apply(obj, args); }; } else { return function (obj) { return obj[func].apply(obj, args); }; } }, /** @id MochiKit.Base.method */ method: function (self, func) { var m = MochiKit.Base; return m.bind.apply(this, m.extend([func, self], arguments, 2)); }, /** @id MochiKit.Base.compose */ compose: function (f1, f2/*, f3, ... fN */) { var fnlist = []; var m = MochiKit.Base; if (arguments.length === 0) { throw new TypeError("compose() requires at least one argument"); } for (var i = 0; i < arguments.length; i++) { var fn = arguments[i]; if (typeof(fn) != "function") { throw new TypeError(m.repr(fn) + " is not a function"); } fnlist.push(fn); } return function () { var args = arguments; for (var i = fnlist.length - 1; i >= 0; i--) { args = [fnlist[i].apply(this, args)]; } return args[0]; }; }, /** @id MochiKit.Base.bind */ bind: function (func, self/* args... */) { if (typeof(func) == "string") { func = self[func]; } var im_func = func.im_func; var im_preargs = func.im_preargs; var im_self = func.im_self; var m = MochiKit.Base; if (typeof(func) == "function" && typeof(func.apply) == "undefined") { // this is for cases where JavaScript sucks ass and gives you a // really dumb built-in function like alert() that doesn't have // an apply func = m._wrapDumbFunction(func); } if (typeof(im_func) != 'function') { im_func = func; } if (typeof(self) != 'undefined') { im_self = self; } if (typeof(im_preargs) == 'undefined') { im_preargs = []; } else { im_preargs = im_preargs.slice(); } m.extend(im_preargs, arguments, 2); var newfunc = function () { var args = arguments; var me = arguments.callee; if (me.im_preargs.length > 0) { args = m.concat(me.im_preargs, args); } var self = me.im_self; if (!self) { self = this; } return me.im_func.apply(self, args); }; newfunc.im_self = im_self; newfunc.im_func = im_func; newfunc.im_preargs = im_preargs; return newfunc; }, /** @id MochiKit.Base.bindLate */ bindLate: function (func, self/* args... */) { var m = MochiKit.Base; if (typeof(func) != "string") { return m.bind.apply(this, arguments); } var im_preargs = m.extend([], arguments, 2); var newfunc = function () { var args = arguments; var me = arguments.callee; if (me.im_preargs.length > 0) { args = m.concat(me.im_preargs, args); } var self = me.im_self; if (!self) { self = this; } return self[me.im_func].apply(self, args); }; newfunc.im_self = self; newfunc.im_func = func; newfunc.im_preargs = im_preargs; return newfunc; }, /** @id MochiKit.Base.bindMethods */ bindMethods: function (self) { var bind = MochiKit.Base.bind; for (var k in self) { var func = self[k]; if (typeof(func) == 'function') { self[k] = bind(func, self); } } }, /** @id MochiKit.Base.registerComparator */ registerComparator: function (name, check, comparator, /* optional */ override) { MochiKit.Base.comparatorRegistry.register(name, check, comparator, override); }, _primitives: {'boolean': true, 'string': true, 'number': true}, /** @id MochiKit.Base.compare */ compare: function (a, b) { if (a == b) { return 0; } var aIsNull = (typeof(a) == 'undefined' || a === null); var bIsNull = (typeof(b) == 'undefined' || b === null); if (aIsNull && bIsNull) { return 0; } else if (aIsNull) { return -1; } else if (bIsNull) { return 1; } var m = MochiKit.Base; // bool, number, string have meaningful comparisons var prim = m._primitives; if (!(typeof(a) in prim && typeof(b) in prim)) { try { return m.comparatorRegistry.match(a, b); } catch (e) { if (e != m.NotFound) { throw e; } } } if (a < b) { return -1; } else if (a > b) { return 1; } // These types can't be compared var repr = m.repr; throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared"); }, /** @id MochiKit.Base.compareDateLike */ compareDateLike: function (a, b) { return MochiKit.Base.compare(a.getTime(), b.getTime()); }, /** @id MochiKit.Base.compareArrayLike */ compareArrayLike: function (a, b) { var compare = MochiKit.Base.compare; var count = a.length; var rval = 0; if (count > b.length) { rval = 1; count = b.length; } else if (count < b.length) { rval = -1; } for (var i = 0; i < count; i++) { var cmp = compare(a[i], b[i]); if (cmp) { return cmp; } } return rval; }, /** @id MochiKit.Base.registerRepr */ registerRepr: function (name, check, wrap, /* optional */override) { MochiKit.Base.reprRegistry.register(name, check, wrap, override); }, /** @id MochiKit.Base.repr */ repr: function (o) { if (typeof(o) == "undefined") { return "undefined"; } else if (o === null) { return "null"; } try { if (typeof(o.__repr__) == 'function') { return o.__repr__(); } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) { return o.repr(); } return MochiKit.Base.reprRegistry.match(o); } catch (e) { if (typeof(o.NAME) == 'string' && ( o.toString == Function.prototype.toString || o.toString == Object.prototype.toString )) { return o.NAME; } } try { var ostring = (o + ""); } catch (e) { return "[" + typeof(o) + "]"; } if (typeof(o) == "function") { ostring = ostring.replace(/^\s+/, "").replace(/\s+/g, " "); ostring = ostring.replace(/,(\S)/, ", $1"); var idx = ostring.indexOf("{"); if (idx != -1) { ostring = ostring.substr(0, idx) + "{...}"; } } return ostring; }, /** @id MochiKit.Base.reprArrayLike */ reprArrayLike: function (o) { var m = MochiKit.Base; return "[" + m.map(m.repr, o).join(", ") + "]"; }, /** @id MochiKit.Base.reprString */ reprString: function (o) { return ('"' + o.replace(/(["\\])/g, '\\$1') + '"' ).replace(/[\f]/g, "\\f" ).replace(/[\b]/g, "\\b" ).replace(/[\n]/g, "\\n" ).replace(/[\t]/g, "\\t" ).replace(/[\v]/g, "\\v" ).replace(/[\r]/g, "\\r"); }, /** @id MochiKit.Base.reprNumber */ reprNumber: function (o) { return o + ""; }, /** @id MochiKit.Base.registerJSON */ registerJSON: function (name, check, wrap, /* optional */override) { MochiKit.Base.jsonRegistry.register(name, check, wrap, override); }, /** @id MochiKit.Base.evalJSON */ evalJSON: function () { return eval("(" + MochiKit.Base._filterJSON(arguments[0]) + ")"); }, _filterJSON: function (s) { var m = s.match(/^\s*\/\*(.*)\*\/\s*$/); if (m) { return m[1]; } return s; }, /** @id MochiKit.Base.serializeJSON */ serializeJSON: function (o) { var objtype = typeof(o); if (objtype == "number" || objtype == "boolean") { return o + ""; } else if (o === null) { return "null"; } else if (objtype == "string") { var res = ""; for (var i = 0; i < o.length; i++) { var c = o.charAt(i); if (c == '\"') { res += '\\"'; } else if (c == '\\') { res += '\\\\'; } else if (c == '\b') { res += '\\b'; } else if (c == '\f') { res += '\\f'; } else if (c == '\n') { res += '\\n'; } else if (c == '\r') { res += '\\r'; } else if (c == '\t') { res += '\\t'; } else if (o.charCodeAt(i) <= 0x1F) { var hex = o.charCodeAt(i).toString(16); if (hex.length < 2) { hex = '0' + hex; } res += '\\u00' + hex.toUpperCase(); } else { res += c; } } return '"' + res + '"'; } // recurse var me = arguments.callee; // short-circuit for objects that support "json" serialization // if they return "self" then just pass-through... var newObj; if (typeof(o.__json__) == "function") { newObj = o.__json__(); if (o !== newObj) { return me(newObj); } } if (typeof(o.json) == "function") { newObj = o.json(); if (o !== newObj) { return me(newObj); } } // array if (objtype != "function" && typeof(o.length) == "number") { var res = []; for (var i = 0; i < o.length; i++) { var val = me(o[i]); if (typeof(val) != "string") { // skip non-serializable values continue; } res.push(val); } return "[" + res.join(", ") + "]"; } // look in the registry var m = MochiKit.Base; try { newObj = m.jsonRegistry.match(o); if (o !== newObj) { return me(newObj); } } catch (e) { if (e != m.NotFound) { // something really bad happened throw e; } } // undefined is outside of the spec if (objtype == "undefined") { throw new TypeError("undefined can not be serialized as JSON"); } // it's a function with no adapter, bad if (objtype == "function") { return null; } // generic object code path res = []; for (var k in o) { var useKey; if (typeof(k) == "number") { useKey = '"' + k + '"'; } else if (typeof(k) == "string") { useKey = me(k); } else { // skip non-string or number keys continue; } val = me(o[k]); if (typeof(val) != "string") { // skip non-serializable values continue; } res.push(useKey + ":" + val); } return "{" + res.join(", ") + "}"; }, /** @id MochiKit.Base.objEqual */ objEqual: function (a, b) { return (MochiKit.Base.compare(a, b) === 0); }, /** @id MochiKit.Base.arrayEqual */ arrayEqual: function (self, arr) { if (self.length != arr.length) { return false; } return (MochiKit.Base.compare(self, arr) === 0); }, /** @id MochiKit.Base.concat */ concat: function (/* lst... */) { var rval = []; var extend = MochiKit.Base.extend; for (var i = 0; i < arguments.length; i++) { extend(rval, arguments[i]); } return rval; }, /** @id MochiKit.Base.keyComparator */ keyComparator: function (key/* ... */) { // fast-path for single key comparisons var m = MochiKit.Base; var compare = m.compare; if (arguments.length == 1) { return function (a, b) { return compare(a[key], b[key]); }; } var compareKeys = m.extend(null, arguments); return function (a, b) { var rval = 0; // keep comparing until something is inequal or we run out of // keys to compare for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) { var key = compareKeys[i]; rval = compare(a[key], b[key]); } return rval; }; }, /** @id MochiKit.Base.reverseKeyComparator */ reverseKeyComparator: function (key) { var comparator = MochiKit.Base.keyComparator.apply(this, arguments); return function (a, b) { return comparator(b, a); }; }, /** @id MochiKit.Base.partial */ partial: function (func) { var m = MochiKit.Base; return m.bind.apply(this, m.extend([func, undefined], arguments, 1)); }, /** @id MochiKit.Base.listMinMax */ listMinMax: function (which, lst) { if (lst.length === 0) { return null; } var cur = lst[0]; var compare = MochiKit.Base.compare; for (var i = 1; i < lst.length; i++) { var o = lst[i]; if (compare(o, cur) == which) { cur = o; } } return cur; }, /** @id MochiKit.Base.objMax */ objMax: function (/* obj... */) { return MochiKit.Base.listMinMax(1, arguments); }, /** @id MochiKit.Base.objMin */ objMin: function (/* obj... */) { return MochiKit.Base.listMinMax(-1, arguments); }, /** @id MochiKit.Base.findIdentical */ findIdentical: function (lst, value, start/* = 0 */, /* optional */end) { if (typeof(end) == "undefined" || end === null) { end = lst.length; } if (typeof(start) == "undefined" || start === null) { start = 0; } for (var i = start; i < end; i++) { if (lst[i] === value) { return i; } } return -1; }, /** @id MochiKit.Base.mean */ mean: function(/* lst... */) { /* http://www.nist.gov/dads/HTML/mean.html */ var sum = 0; var m = MochiKit.Base; var args = m.extend(null, arguments); var count = args.length; while (args.length) { var o = args.shift(); if (o && typeof(o) == "object" && typeof(o.length) == "number") { count += o.length - 1; for (var i = o.length - 1; i >= 0; i--) { sum += o[i]; } } else { sum += o; } } if (count <= 0) { throw new TypeError('mean() requires at least one argument'); } return sum/count; }, /** @id MochiKit.Base.median */ median: function(/* lst... */) { /* http://www.nist.gov/dads/HTML/median.html */ var data = MochiKit.Base.flattenArguments(arguments); if (data.length === 0) { throw new TypeError('median() requires at least one argument'); } data.sort(compare); if (data.length % 2 == 0) { var upper = data.length / 2; return (data[upper] + data[upper - 1]) / 2; } else { return data[(data.length - 1) / 2]; } }, /** @id MochiKit.Base.findValue */ findValue: function (lst, value, start/* = 0 */, /* optional */end) { if (typeof(end) == "undefined" || end === null) { end = lst.length; } if (typeof(start) == "undefined" || start === null) { start = 0; } var cmp = MochiKit.Base.compare; for (var i = start; i < end; i++) { if (cmp(lst[i], value) === 0) { return i; } } return -1; }, /** @id MochiKit.Base.nodeWalk */ nodeWalk: function (node, visitor) { var nodes = [node]; var extend = MochiKit.Base.extend; while (nodes.length) { var res = visitor(nodes.shift()); if (res) { extend(nodes, res); } } }, /** @id MochiKit.Base.nameFunctions */ nameFunctions: function (namespace) { var base = namespace.NAME; if (typeof(base) == 'undefined') { base = ''; } else { base = base + '.'; } for (var name in namespace) { var o = namespace[name]; if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') { try { o.NAME = base + name; } catch (e) { // pass } } } }, /** @id MochiKit.Base.queryString */ queryString: function (names, values) { // check to see if names is a string or a DOM element, and if // MochiKit.DOM is available. If so, drop it like it's a form // Ugliest conditional in MochiKit? Probably! if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1 && (typeof(names) == "string" || ( typeof(names.nodeType) != "undefined" && names.nodeType > 0 )) ) { var kv = MochiKit.DOM.formContents(names); names = kv[0]; values = kv[1]; } else if (arguments.length == 1) { // Allow the return value of formContents to be passed directly if (typeof(names.length) == "number" && names.length == 2) { return arguments.callee(names[0], names[1]); } var o = names; names = []; values = []; for (var k in o) { var v = o[k]; if (typeof(v) == "function") { continue; } else if (MochiKit.Base.isArrayLike(v)){ for (var i = 0; i < v.length; i++) { names.push(k); values.push(v[i]); } } else { names.push(k); values.push(v); } } } var rval = []; var len = Math.min(names.length, values.length); var urlEncode = MochiKit.Base.urlEncode; for (var i = 0; i < len; i++) { v = values[i]; if (typeof(v) != 'undefined' && v !== null) { rval.push(urlEncode(names[i]) + "=" + urlEncode(v)); } } return rval.join("&"); }, /** @id MochiKit.Base.parseQueryString */ parseQueryString: function (encodedString, useArrays) { // strip a leading '?' from the encoded string var qstr = (encodedString.charAt(0) == "?") ? encodedString.substring(1) : encodedString; var pairs = qstr.replace(/\+/g, "%20").split(/\&\;|\&\#38\;|\&|\&/); var o = {}; var decode; if (typeof(decodeURIComponent) != "undefined") { decode = decodeURIComponent; } else { decode = unescape; } if (useArrays) { for (var i = 0; i < pairs.length; i++) { var pair = pairs[i].split("="); var name = decode(pair.shift()); if (!name) { continue; } var arr = o[name]; if (!(arr instanceof Array)) { arr = []; o[name] = arr; } arr.push(decode(pair.join("="))); } } else { for (i = 0; i < pairs.length; i++) { pair = pairs[i].split("="); var name = pair.shift(); if (!name) { continue; } o[decode(name)] = decode(pair.join("=")); } } return o; } }); /** @id MochiKit.Base.AdapterRegistry */ MochiKit.Base.AdapterRegistry = function () { this.pairs = []; }; MochiKit.Base.AdapterRegistry.prototype = { /** @id MochiKit.Base.AdapterRegistry.prototype.register */ register: function (name, check, wrap, /* optional */ override) { if (override) { this.pairs.unshift([name, check, wrap]); } else { this.pairs.push([name, check, wrap]); } }, /** @id MochiKit.Base.AdapterRegistry.prototype.match */ match: function (/* ... */) { for (var i = 0; i < this.pairs.length; i++) { var pair = this.pairs[i]; if (pair[1].apply(this, arguments)) { return pair[2].apply(this, arguments); } } throw MochiKit.Base.NotFound; }, /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */ unregister: function (name) { for (var i = 0; i < this.pairs.length; i++) { var pair = this.pairs[i]; if (pair[0] == name) { this.pairs.splice(i, 1); return true; } } return false; } }; MochiKit.Base.EXPORT = [ "flattenArray", "noop", "camelize", "counter", "clone", "extend", "update", "updatetree", "setdefault", "keys", "values", "items", "NamedError", "operator", "forwardCall", "itemgetter", "typeMatcher", "isCallable", "isUndefined", "isUndefinedOrNull", "isNull", "isEmpty", "isNotEmpty", "isArrayLike", "isDateLike", "xmap", "map", "xfilter", "filter", "methodcaller", "compose", "bind", "bindLate", "bindMethods", "NotFound", "AdapterRegistry", "registerComparator", "compare", "registerRepr", "repr", "objEqual", "arrayEqual", "concat", "keyComparator", "reverseKeyComparator", "partial", "merge", "listMinMax", "listMax", "listMin", "objMax", "objMin", "nodeWalk", "zip", "urlEncode", "queryString", "serializeJSON", "registerJSON", "evalJSON", "parseQueryString", "findValue", "findIdentical", "flattenArguments", "method", "average", "mean", "median" ]; MochiKit.Base.EXPORT_OK = [ "nameFunctions", "comparatorRegistry", "reprRegistry", "jsonRegistry", "compareDateLike", "compareArrayLike", "reprArrayLike", "reprString", "reprNumber" ]; MochiKit.Base._exportSymbols = function (globals, module) { if (!MochiKit.__export__) { return; } var all = module.EXPORT_TAGS[":all"]; for (var i = 0; i < all.length; i++) { globals[all[i]] = module[all[i]]; } }; MochiKit.Base.__new__ = function () { // A singleton raised when no suitable adapter is found var m = this; // convenience /** @id MochiKit.Base.noop */ m.noop = m.operator.identity; // Backwards compat m.forward = m.forwardCall; m.find = m.findValue; if (typeof(encodeURIComponent) != "undefined") { /** @id MochiKit.Base.urlEncode */ m.urlEncode = function (unencoded) { return encodeURIComponent(unencoded).replace(/\'/g, '%27'); }; } else { m.urlEncode = function (unencoded) { return escape(unencoded ).replace(/\+/g, '%2B' ).replace(/\"/g,'%22' ).rval.replace(/\'/g, '%27'); }; } /** @id MochiKit.Base.NamedError */ m.NamedError = function (name) { this.message = name; this.name = name; }; m.NamedError.prototype = new Error(); m.update(m.NamedError.prototype, { repr: function () { if (this.message && this.message != this.name) { return this.name + "(" + m.repr(this.message) + ")"; } else { return this.name + "()"; } }, toString: m.forwardCall("repr") }); /** @id MochiKit.Base.NotFound */ m.NotFound = new m.NamedError("MochiKit.Base.NotFound"); /** @id MochiKit.Base.listMax */ m.listMax = m.partial(m.listMinMax, 1); /** @id MochiKit.Base.listMin */ m.listMin = m.partial(m.listMinMax, -1); /** @id MochiKit.Base.isCallable */ m.isCallable = m.typeMatcher('function'); /** @id MochiKit.Base.isUndefined */ m.isUndefined = m.typeMatcher('undefined'); /** @id MochiKit.Base.merge */ m.merge = m.partial(m.update, null); /** @id MochiKit.Base.zip */ m.zip = m.partial(m.map, null); /** @id MochiKit.Base.average */ m.average = m.mean; /** @id MochiKit.Base.comparatorRegistry */ m.comparatorRegistry = new m.AdapterRegistry(); m.registerComparator("dateLike", m.isDateLike, m.compareDateLike); m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike); /** @id MochiKit.Base.reprRegistry */ m.reprRegistry = new m.AdapterRegistry(); m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike); m.registerRepr("string", m.typeMatcher("string"), m.reprString); m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber); /** @id MochiKit.Base.jsonRegistry */ m.jsonRegistry = new m.AdapterRegistry(); var all = m.concat(m.EXPORT, m.EXPORT_OK); m.EXPORT_TAGS = { ":common": m.concat(m.EXPORT_OK), ":all": all }; m.nameFunctions(this); }; MochiKit.Base.__new__(); // // XXX: Internet Explorer blows // if (MochiKit.__export__) { compare = MochiKit.Base.compare; compose = MochiKit.Base.compose; serializeJSON = MochiKit.Base.serializeJSON; mean = MochiKit.Base.mean; median = MochiKit.Base.median; } MochiKit.Base._exportSymbols(this, MochiKit.Base); MochiKit-1.4.2/lib/MochiKit/__package__.js0000660000175000017500000000065511102215572017301 0ustar scottscottdojo.kwCompoundRequire({ "common": [ "MochiKit.Base", "MochiKit.Iter", "MochiKit.Logging", "MochiKit.DateTime", "MochiKit.Format", "MochiKit.Async", "MochiKit.DOM", "MochiKit.Style", "MochiKit.LoggingPane", "MochiKit.Color", "MochiKit.Signal", "MochiKit.Position", "MochiKit.Visual" ] }); dojo.provide("MochiKit.*"); MochiKit-1.4.2/lib/MochiKit/LoggingPane.js0000660000175000017500000002537411110670064017311 0ustar scottscott/*** MochiKit.LoggingPane 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('LoggingPane', ['Base', 'Logging']); MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane"; MochiKit.LoggingPane.VERSION = "1.4.2"; MochiKit.LoggingPane.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.LoggingPane.toString = function () { return this.__repr__(); }; /** @id MochiKit.LoggingPane.createLoggingPane */ MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) { var m = MochiKit.LoggingPane; inline = !(!inline); if (m._loggingPane && m._loggingPane.inline != inline) { m._loggingPane.closePane(); m._loggingPane = null; } if (!m._loggingPane || m._loggingPane.closed) { m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger); } return m._loggingPane; }; /** @id MochiKit.LoggingPane.LoggingPane */ MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) { /* Use a div if inline, pop up a window if not */ /* Create the elements */ if (typeof(logger) == "undefined" || logger === null) { logger = MochiKit.Logging.logger; } this.logger = logger; var update = MochiKit.Base.update; var updatetree = MochiKit.Base.updatetree; var bind = MochiKit.Base.bind; var clone = MochiKit.Base.clone; var win = window; var uid = "_MochiKit_LoggingPane"; if (typeof(MochiKit.DOM) != "undefined") { win = MochiKit.DOM.currentWindow(); } if (!inline) { // name the popup with the base URL for uniqueness var url = win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g, "_"); var name = uid + "_" + url; var nwin = win.open("", name, "dependent,resizable,height=200"); if (!nwin) { alert("Not able to open debugging window due to pop-up blocking."); return undefined; } nwin.document.write( '' + '[MochiKit.LoggingPane]' + '' ); nwin.document.close(); nwin.document.title += ' ' + win.document.title; win = nwin; } var doc = win.document; this.doc = doc; // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed) var debugPane = doc.getElementById(uid); var existing_pane = !!debugPane; if (debugPane && typeof(debugPane.loggingPane) != "undefined") { debugPane.loggingPane.logger = this.logger; debugPane.loggingPane.buildAndApplyFilter(); return debugPane.loggingPane; } if (existing_pane) { // clear any existing contents var child; while ((child = debugPane.firstChild)) { debugPane.removeChild(child); } } else { debugPane = doc.createElement("div"); debugPane.id = uid; } debugPane.loggingPane = this; var levelFilterField = doc.createElement("input"); var infoFilterField = doc.createElement("input"); var filterButton = doc.createElement("button"); var loadButton = doc.createElement("button"); var clearButton = doc.createElement("button"); var closeButton = doc.createElement("button"); var logPaneArea = doc.createElement("div"); var logPane = doc.createElement("div"); /* Set up the functions */ var listenerId = uid + "_Listener"; this.colorTable = clone(this.colorTable); var messages = []; var messageFilter = null; /** @id MochiKit.LoggingPane.messageLevel */ var messageLevel = function (msg) { var level = msg.level; if (typeof(level) == "number") { level = MochiKit.Logging.LogLevel[level]; } return level; }; /** @id MochiKit.LoggingPane.messageText */ var messageText = function (msg) { return msg.info.join(" "); }; /** @id MochiKit.LoggingPane.addMessageText */ var addMessageText = bind(function (msg) { var level = messageLevel(msg); var text = messageText(msg); var c = this.colorTable[level]; var p = doc.createElement("span"); p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level; p.style.cssText = "margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: " + c; p.appendChild(doc.createTextNode(level + ": " + text)); logPane.appendChild(p); logPane.appendChild(doc.createElement("br")); if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) { logPaneArea.scrollTop = 0; } else { logPaneArea.scrollTop = logPaneArea.scrollHeight; } }, this); /** @id MochiKit.LoggingPane.addMessage */ var addMessage = function (msg) { messages[messages.length] = msg; addMessageText(msg); }; /** @id MochiKit.LoggingPane.buildMessageFilter */ var buildMessageFilter = function () { var levelre, infore; try { /* Catch any exceptions that might arise due to invalid regexes */ levelre = new RegExp(levelFilterField.value); infore = new RegExp(infoFilterField.value); } catch(e) { /* If there was an error with the regexes, do no filtering */ logDebug("Error in filter regex: " + e.message); return null; } return function (msg) { return ( levelre.test(messageLevel(msg)) && infore.test(messageText(msg)) ); }; }; /** @id MochiKit.LoggingPane.clearMessagePane */ var clearMessagePane = function () { while (logPane.firstChild) { logPane.removeChild(logPane.firstChild); } }; /** @id MochiKit.LoggingPane.clearMessages */ var clearMessages = function () { messages = []; clearMessagePane(); }; /** @id MochiKit.LoggingPane.closePane */ var closePane = bind(function () { if (this.closed) { return; } this.closed = true; if (MochiKit.LoggingPane._loggingPane == this) { MochiKit.LoggingPane._loggingPane = null; } this.logger.removeListener(listenerId); try { try { debugPane.loggingPane = null; } catch(e) { logFatal("Bookmarklet was closed incorrectly."); } if (inline) { debugPane.parentNode.removeChild(debugPane); } else { this.win.close(); } } catch(e) {} }, this); /** @id MochiKit.LoggingPane.filterMessages */ var filterMessages = function () { clearMessagePane(); for (var i = 0; i < messages.length; i++) { var msg = messages[i]; if (messageFilter === null || messageFilter(msg)) { addMessageText(msg); } } }; this.buildAndApplyFilter = function () { messageFilter = buildMessageFilter(); filterMessages(); this.logger.removeListener(listenerId); this.logger.addListener(listenerId, messageFilter, addMessage); }; /** @id MochiKit.LoggingPane.loadMessages */ var loadMessages = bind(function () { messages = this.logger.getMessages(); filterMessages(); }, this); /** @id MochiKit.LoggingPane.filterOnEnter */ var filterOnEnter = bind(function (event) { event = event || window.event; key = event.which || event.keyCode; if (key == 13) { this.buildAndApplyFilter(); } }, this); /* Create the debug pane */ var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont; if (inline) { style += "; height: 10em; border-top: 2px solid black"; } else { style += "; height: 100%;"; } debugPane.style.cssText = style; if (!existing_pane) { doc.body.appendChild(debugPane); } /* Create the filter fields */ style = {"cssText": "width: 33%; display: inline; font: " + this.logFont}; updatetree(levelFilterField, { "value": "FATAL|ERROR|WARNING|INFO|DEBUG", "onkeypress": filterOnEnter, "style": style }); debugPane.appendChild(levelFilterField); updatetree(infoFilterField, { "value": ".*", "onkeypress": filterOnEnter, "style": style }); debugPane.appendChild(infoFilterField); /* Create the buttons */ style = "width: 8%; display:inline; font: " + this.logFont; filterButton.appendChild(doc.createTextNode("Filter")); filterButton.onclick = bind("buildAndApplyFilter", this); filterButton.style.cssText = style; debugPane.appendChild(filterButton); loadButton.appendChild(doc.createTextNode("Load")); loadButton.onclick = loadMessages; loadButton.style.cssText = style; debugPane.appendChild(loadButton); clearButton.appendChild(doc.createTextNode("Clear")); clearButton.onclick = clearMessages; clearButton.style.cssText = style; debugPane.appendChild(clearButton); closeButton.appendChild(doc.createTextNode("Close")); closeButton.onclick = closePane; closeButton.style.cssText = style; debugPane.appendChild(closeButton); /* Create the logging pane */ logPaneArea.style.cssText = "overflow: auto; width: 100%"; logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%"); logPaneArea.appendChild(logPane); debugPane.appendChild(logPaneArea); this.buildAndApplyFilter(); loadMessages(); if (inline) { this.win = undefined; } else { this.win = win; } this.inline = inline; this.closePane = closePane; this.closed = false; return this; }; MochiKit.LoggingPane.LoggingPane.prototype = { "logFont": "8pt Verdana,sans-serif", "colorTable": { "ERROR": "red", "FATAL": "darkred", "WARNING": "blue", "INFO": "black", "DEBUG": "green" } }; MochiKit.LoggingPane.EXPORT_OK = [ "LoggingPane" ]; MochiKit.LoggingPane.EXPORT = [ "createLoggingPane" ]; MochiKit.LoggingPane.__new__ = function () { this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) }; MochiKit.Base.nameFunctions(this); MochiKit.LoggingPane._loggingPane = null; }; MochiKit.LoggingPane.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane); MochiKit-1.4.2/lib/MochiKit/DOM.js0000660000175000017500000012116411113644770015540 0ustar scottscott/*** MochiKit.DOM 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('DOM', ['Base']); MochiKit.DOM.NAME = "MochiKit.DOM"; MochiKit.DOM.VERSION = "1.4.2"; MochiKit.DOM.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.DOM.toString = function () { return this.__repr__(); }; MochiKit.DOM.EXPORT = [ "removeEmptyTextNodes", "formContents", "currentWindow", "currentDocument", "withWindow", "withDocument", "registerDOMConverter", "coerceToDOM", "createDOM", "createDOMFunc", "isChildNode", "getNodeAttribute", "removeNodeAttribute", "setNodeAttribute", "updateNodeAttributes", "appendChildNodes", "insertSiblingNodesAfter", "insertSiblingNodesBefore", "replaceChildNodes", "removeElement", "swapDOM", "BUTTON", "TT", "PRE", "H1", "H2", "H3", "H4", "H5", "H6", "BR", "CANVAS", "HR", "LABEL", "TEXTAREA", "FORM", "STRONG", "SELECT", "OPTION", "OPTGROUP", "LEGEND", "FIELDSET", "P", "UL", "OL", "LI", "DL", "DT", "DD", "TD", "TR", "THEAD", "TBODY", "TFOOT", "TABLE", "TH", "INPUT", "SPAN", "A", "DIV", "IMG", "getElement", "$", "getElementsByTagAndClassName", "addToCallStack", "addLoadEvent", "focusOnLoad", "setElementClass", "toggleElementClass", "addElementClass", "removeElementClass", "swapElementClass", "hasElementClass", "computedStyle", // deprecated in 1.4 "escapeHTML", "toHTML", "emitHTML", "scrapeText", "getFirstParentByTagAndClassName", "getFirstElementByTagAndClassName" ]; MochiKit.DOM.EXPORT_OK = [ "domConverters" ]; MochiKit.DOM.DEPRECATED = [ /** @id MochiKit.DOM.computedStyle */ ['computedStyle', 'MochiKit.Style.getStyle', '1.4'], /** @id MochiKit.DOM.elementDimensions */ ['elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4'], /** @id MochiKit.DOM.elementPosition */ ['elementPosition', 'MochiKit.Style.getElementPosition', '1.4'], /** @id MochiKit.DOM.getViewportDimensions */ ['getViewportDimensions', 'MochiKit.Style.getViewportDimensions', '1.4'], /** @id MochiKit.DOM.hideElement */ ['hideElement', 'MochiKit.Style.hideElement', '1.4'], /** @id MochiKit.DOM.makeClipping */ ['makeClipping', 'MochiKit.Style.makeClipping', '1.4.1'], /** @id MochiKit.DOM.makePositioned */ ['makePositioned', 'MochiKit.Style.makePositioned', '1.4.1'], /** @id MochiKit.DOM.setElementDimensions */ ['setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4'], /** @id MochiKit.DOM.setElementPosition */ ['setElementPosition', 'MochiKit.Style.setElementPosition', '1.4'], /** @id MochiKit.DOM.setDisplayForElement */ ['setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4'], /** @id MochiKit.DOM.setOpacity */ ['setOpacity', 'MochiKit.Style.setOpacity', '1.4'], /** @id MochiKit.DOM.showElement */ ['showElement', 'MochiKit.Style.showElement', '1.4'], /** @id MochiKit.DOM.undoClipping */ ['undoClipping', 'MochiKit.Style.undoClipping', '1.4.1'], /** @id MochiKit.DOM.undoPositioned */ ['undoPositioned', 'MochiKit.Style.undoPositioned', '1.4.1'], /** @id MochiKit.DOM.Coordinates */ ['Coordinates', 'MochiKit.Style.Coordinates', '1.4'], // FIXME: broken /** @id MochiKit.DOM.Dimensions */ ['Dimensions', 'MochiKit.Style.Dimensions', '1.4'] // FIXME: broken ]; MochiKit.Base.update(MochiKit.DOM, { /** @id MochiKit.DOM.currentWindow */ currentWindow: function () { return MochiKit.DOM._window; }, /** @id MochiKit.DOM.currentDocument */ currentDocument: function () { return MochiKit.DOM._document; }, /** @id MochiKit.DOM.withWindow */ withWindow: function (win, func) { var self = MochiKit.DOM; var oldDoc = self._document; var oldWin = self._window; var rval; try { self._window = win; self._document = win.document; rval = func(); } catch (e) { self._window = oldWin; self._document = oldDoc; throw e; } self._window = oldWin; self._document = oldDoc; return rval; }, /** @id MochiKit.DOM.formContents */ formContents: function (elem/* = document.body */) { var names = []; var values = []; var m = MochiKit.Base; var self = MochiKit.DOM; if (typeof(elem) == "undefined" || elem === null) { elem = self._document.body; } else { elem = self.getElement(elem); } m.nodeWalk(elem, function (elem) { var name = elem.name; if (m.isNotEmpty(name)) { var tagName = elem.tagName.toUpperCase(); if (tagName === "INPUT" && (elem.type == "radio" || elem.type == "checkbox") && !elem.checked ) { return null; } if (tagName === "SELECT") { if (elem.type == "select-one") { if (elem.selectedIndex >= 0) { var opt = elem.options[elem.selectedIndex]; var v = opt.value; if (!v) { var h = opt.outerHTML; // internet explorer sure does suck. if (h && !h.match(/^[^>]+\svalue\s*=/i)) { v = opt.text; } } names.push(name); values.push(v); return null; } // no form elements? names.push(name); values.push(""); return null; } else { var opts = elem.options; if (!opts.length) { names.push(name); values.push(""); return null; } for (var i = 0; i < opts.length; i++) { var opt = opts[i]; if (!opt.selected) { continue; } var v = opt.value; if (!v) { var h = opt.outerHTML; // internet explorer sure does suck. if (h && !h.match(/^[^>]+\svalue\s*=/i)) { v = opt.text; } } names.push(name); values.push(v); } return null; } } if (tagName === "FORM" || tagName === "P" || tagName === "SPAN" || tagName === "DIV" ) { return elem.childNodes; } names.push(name); values.push(elem.value || ''); return null; } return elem.childNodes; }); return [names, values]; }, /** @id MochiKit.DOM.withDocument */ withDocument: function (doc, func) { var self = MochiKit.DOM; var oldDoc = self._document; var rval; try { self._document = doc; rval = func(); } catch (e) { self._document = oldDoc; throw e; } self._document = oldDoc; return rval; }, /** @id MochiKit.DOM.registerDOMConverter */ registerDOMConverter: function (name, check, wrap, /* optional */override) { MochiKit.DOM.domConverters.register(name, check, wrap, override); }, /** @id MochiKit.DOM.coerceToDOM */ coerceToDOM: function (node, ctx) { var m = MochiKit.Base; var im = MochiKit.Iter; var self = MochiKit.DOM; if (im) { var iter = im.iter; var repeat = im.repeat; } var map = m.map; var domConverters = self.domConverters; var coerceToDOM = arguments.callee; var NotFound = m.NotFound; while (true) { if (typeof(node) == 'undefined' || node === null) { return null; } // this is a safari childNodes object, avoiding crashes w/ attr // lookup if (typeof(node) == "function" && typeof(node.length) == "number" && !(node instanceof Function)) { node = im ? im.list(node) : m.extend(null, node); } if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) { return node; } if (typeof(node) == 'number' || typeof(node) == 'boolean') { node = node.toString(); // FALL THROUGH } if (typeof(node) == 'string') { return self._document.createTextNode(node); } if (typeof(node.__dom__) == 'function') { node = node.__dom__(ctx); continue; } if (typeof(node.dom) == 'function') { node = node.dom(ctx); continue; } if (typeof(node) == 'function') { node = node.apply(ctx, [ctx]); continue; } if (im) { // iterable var iterNodes = null; try { iterNodes = iter(node); } catch (e) { // pass } if (iterNodes) { return map(coerceToDOM, iterNodes, repeat(ctx)); } } else if (m.isArrayLike(node)) { var func = function (n) { return coerceToDOM(n, ctx); }; return map(func, node); } // adapter try { node = domConverters.match(node, ctx); continue; } catch (e) { if (e != NotFound) { throw e; } } // fallback return self._document.createTextNode(node.toString()); } // mozilla warnings aren't too bright return undefined; }, /** @id MochiKit.DOM.isChildNode */ isChildNode: function (node, maybeparent) { var self = MochiKit.DOM; if (typeof(node) == "string") { node = self.getElement(node); } if (typeof(maybeparent) == "string") { maybeparent = self.getElement(maybeparent); } if (typeof(node) == 'undefined' || node === null) { return false; } while (node != null && node !== self._document) { if (node === maybeparent) { return true; } node = node.parentNode; } return false; }, /** @id MochiKit.DOM.setNodeAttribute */ setNodeAttribute: function (node, attr, value) { var o = {}; o[attr] = value; try { return MochiKit.DOM.updateNodeAttributes(node, o); } catch (e) { // pass } return null; }, /** @id MochiKit.DOM.getNodeAttribute */ getNodeAttribute: function (node, attr) { var self = MochiKit.DOM; var rename = self.attributeArray.renames[attr]; var ignoreValue = self.attributeArray.ignoreAttr[attr]; node = self.getElement(node); try { if (rename) { return node[rename]; } var value = node.getAttribute(attr); if (value != ignoreValue) { return value; } } catch (e) { // pass } return null; }, /** @id MochiKit.DOM.removeNodeAttribute */ removeNodeAttribute: function (node, attr) { var self = MochiKit.DOM; var rename = self.attributeArray.renames[attr]; node = self.getElement(node); try { if (rename) { return node[rename]; } return node.removeAttribute(attr); } catch (e) { // pass } return null; }, /** @id MochiKit.DOM.updateNodeAttributes */ updateNodeAttributes: function (node, attrs) { var elem = node; var self = MochiKit.DOM; if (typeof(node) == 'string') { elem = self.getElement(node); } if (attrs) { var updatetree = MochiKit.Base.updatetree; if (self.attributeArray.compliant) { // not IE, good. for (var k in attrs) { var v = attrs[k]; if (typeof(v) == 'object' && typeof(elem[k]) == 'object') { if (k == "style" && MochiKit.Style) { MochiKit.Style.setStyle(elem, v); } else { updatetree(elem[k], v); } } else if (k.substring(0, 2) == "on") { if (typeof(v) == "string") { v = new Function(v); } elem[k] = v; } else { elem.setAttribute(k, v); } if (typeof(elem[k]) == "string" && elem[k] != v) { // Also set property for weird attributes (see #302) elem[k] = v; } } } else { // IE is insane in the membrane var renames = self.attributeArray.renames; for (var k in attrs) { v = attrs[k]; var renamed = renames[k]; if (k == "style" && typeof(v) == "string") { elem.style.cssText = v; } else if (typeof(renamed) == "string") { elem[renamed] = v; } else if (typeof(elem[k]) == 'object' && typeof(v) == 'object') { if (k == "style" && MochiKit.Style) { MochiKit.Style.setStyle(elem, v); } else { updatetree(elem[k], v); } } else if (k.substring(0, 2) == "on") { if (typeof(v) == "string") { v = new Function(v); } elem[k] = v; } else { elem.setAttribute(k, v); } if (typeof(elem[k]) == "string" && elem[k] != v) { // Also set property for weird attributes (see #302) elem[k] = v; } } } } return elem; }, /** @id MochiKit.DOM.appendChildNodes */ appendChildNodes: function (node/*, nodes...*/) { var elem = node; var self = MochiKit.DOM; if (typeof(node) == 'string') { elem = self.getElement(node); } var nodeStack = [ self.coerceToDOM( MochiKit.Base.extend(null, arguments, 1), elem ) ]; var concat = MochiKit.Base.concat; while (nodeStack.length) { var n = nodeStack.shift(); if (typeof(n) == 'undefined' || n === null) { // pass } else if (typeof(n.nodeType) == 'number') { elem.appendChild(n); } else { nodeStack = concat(n, nodeStack); } } return elem; }, /** @id MochiKit.DOM.insertSiblingNodesBefore */ insertSiblingNodesBefore: function (node/*, nodes...*/) { var elem = node; var self = MochiKit.DOM; if (typeof(node) == 'string') { elem = self.getElement(node); } var nodeStack = [ self.coerceToDOM( MochiKit.Base.extend(null, arguments, 1), elem ) ]; var parentnode = elem.parentNode; var concat = MochiKit.Base.concat; while (nodeStack.length) { var n = nodeStack.shift(); if (typeof(n) == 'undefined' || n === null) { // pass } else if (typeof(n.nodeType) == 'number') { parentnode.insertBefore(n, elem); } else { nodeStack = concat(n, nodeStack); } } return parentnode; }, /** @id MochiKit.DOM.insertSiblingNodesAfter */ insertSiblingNodesAfter: function (node/*, nodes...*/) { var elem = node; var self = MochiKit.DOM; if (typeof(node) == 'string') { elem = self.getElement(node); } var nodeStack = [ self.coerceToDOM( MochiKit.Base.extend(null, arguments, 1), elem ) ]; if (elem.nextSibling) { return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack); } else { return self.appendChildNodes(elem.parentNode, nodeStack); } }, /** @id MochiKit.DOM.replaceChildNodes */ replaceChildNodes: function (node/*, nodes...*/) { var elem = node; var self = MochiKit.DOM; if (typeof(node) == 'string') { elem = self.getElement(node); arguments[0] = elem; } var child; while ((child = elem.firstChild)) { elem.removeChild(child); } if (arguments.length < 2) { return elem; } else { return self.appendChildNodes.apply(this, arguments); } }, /** @id MochiKit.DOM.createDOM */ createDOM: function (name, attrs/*, nodes... */) { var elem; var self = MochiKit.DOM; var m = MochiKit.Base; if (typeof(attrs) == "string" || typeof(attrs) == "number") { var args = m.extend([name, null], arguments, 1); return arguments.callee.apply(this, args); } if (typeof(name) == 'string') { // Internet Explorer is dumb var xhtml = self._xhtml; if (attrs && !self.attributeArray.compliant) { // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp var contents = ""; if ('name' in attrs) { contents += ' name="' + self.escapeHTML(attrs.name) + '"'; } if (name == 'input' && 'type' in attrs) { contents += ' type="' + self.escapeHTML(attrs.type) + '"'; } if (contents) { name = "<" + name + contents + ">"; xhtml = false; } } var d = self._document; if (xhtml && d === document) { elem = d.createElementNS("http://www.w3.org/1999/xhtml", name); } else { elem = d.createElement(name); } } else { elem = name; } if (attrs) { self.updateNodeAttributes(elem, attrs); } if (arguments.length <= 2) { return elem; } else { var args = m.extend([elem], arguments, 2); return self.appendChildNodes.apply(this, args); } }, /** @id MochiKit.DOM.createDOMFunc */ createDOMFunc: function (/* tag, attrs, *nodes */) { var m = MochiKit.Base; return m.partial.apply( this, m.extend([MochiKit.DOM.createDOM], arguments) ); }, /** @id MochiKit.DOM.removeElement */ removeElement: function (elem) { var self = MochiKit.DOM; var e = self.coerceToDOM(self.getElement(elem)); e.parentNode.removeChild(e); return e; }, /** @id MochiKit.DOM.swapDOM */ swapDOM: function (dest, src) { var self = MochiKit.DOM; dest = self.getElement(dest); var parent = dest.parentNode; if (src) { src = self.coerceToDOM(self.getElement(src), parent); parent.replaceChild(src, dest); } else { parent.removeChild(dest); } return src; }, /** @id MochiKit.DOM.getElement */ getElement: function (id) { var self = MochiKit.DOM; if (arguments.length == 1) { return ((typeof(id) == "string") ? self._document.getElementById(id) : id); } else { return MochiKit.Base.map(self.getElement, arguments); } }, /** @id MochiKit.DOM.getElementsByTagAndClassName */ getElementsByTagAndClassName: function (tagName, className, /* optional */parent) { var self = MochiKit.DOM; if (typeof(tagName) == 'undefined' || tagName === null) { tagName = '*'; } if (typeof(parent) == 'undefined' || parent === null) { parent = self._document; } parent = self.getElement(parent); if (parent == null) { return []; } var children = (parent.getElementsByTagName(tagName) || self._document.all); if (typeof(className) == 'undefined' || className === null) { return MochiKit.Base.extend(null, children); } var elements = []; for (var i = 0; i < children.length; i++) { var child = children[i]; var cls = child.className; if (typeof(cls) != "string") { cls = child.getAttribute("class"); } if (typeof(cls) == "string") { var classNames = cls.split(' '); for (var j = 0; j < classNames.length; j++) { if (classNames[j] == className) { elements.push(child); break; } } } } return elements; }, _newCallStack: function (path, once) { var rval = function () { var callStack = arguments.callee.callStack; for (var i = 0; i < callStack.length; i++) { if (callStack[i].apply(this, arguments) === false) { break; } } if (once) { try { this[path] = null; } catch (e) { // pass } } }; rval.callStack = []; return rval; }, /** @id MochiKit.DOM.addToCallStack */ addToCallStack: function (target, path, func, once) { var self = MochiKit.DOM; var existing = target[path]; var regfunc = existing; if (!(typeof(existing) == 'function' && typeof(existing.callStack) == "object" && existing.callStack !== null)) { regfunc = self._newCallStack(path, once); if (typeof(existing) == 'function') { regfunc.callStack.push(existing); } target[path] = regfunc; } regfunc.callStack.push(func); }, /** @id MochiKit.DOM.addLoadEvent */ addLoadEvent: function (func) { var self = MochiKit.DOM; self.addToCallStack(self._window, "onload", func, true); }, /** @id MochiKit.DOM.focusOnLoad */ focusOnLoad: function (element) { var self = MochiKit.DOM; self.addLoadEvent(function () { element = self.getElement(element); if (element) { element.focus(); } }); }, /** @id MochiKit.DOM.setElementClass */ setElementClass: function (element, className) { var self = MochiKit.DOM; var obj = self.getElement(element); if (self.attributeArray.compliant) { obj.setAttribute("class", className); } else { obj.setAttribute("className", className); } }, /** @id MochiKit.DOM.toggleElementClass */ toggleElementClass: function (className/*, element... */) { var self = MochiKit.DOM; for (var i = 1; i < arguments.length; i++) { var obj = self.getElement(arguments[i]); if (!self.addElementClass(obj, className)) { self.removeElementClass(obj, className); } } }, /** @id MochiKit.DOM.addElementClass */ addElementClass: function (element, className) { var self = MochiKit.DOM; var obj = self.getElement(element); var cls = obj.className; if (typeof(cls) != "string") { cls = obj.getAttribute("class"); } // trivial case, no className yet if (typeof(cls) != "string" || cls.length === 0) { self.setElementClass(obj, className); return true; } // the other trivial case, already set as the only class if (cls == className) { return false; } var classes = cls.split(" "); for (var i = 0; i < classes.length; i++) { // already present if (classes[i] == className) { return false; } } // append class self.setElementClass(obj, cls + " " + className); return true; }, /** @id MochiKit.DOM.removeElementClass */ removeElementClass: function (element, className) { var self = MochiKit.DOM; var obj = self.getElement(element); var cls = obj.className; if (typeof(cls) != "string") { cls = obj.getAttribute("class"); } // trivial case, no className yet if (typeof(cls) != "string" || cls.length === 0) { return false; } // other trivial case, set only to className if (cls == className) { self.setElementClass(obj, ""); return true; } var classes = cls.split(" "); for (var i = 0; i < classes.length; i++) { // already present if (classes[i] == className) { // only check sane case where the class is used once classes.splice(i, 1); self.setElementClass(obj, classes.join(" ")); return true; } } // not found return false; }, /** @id MochiKit.DOM.swapElementClass */ swapElementClass: function (element, fromClass, toClass) { var obj = MochiKit.DOM.getElement(element); var res = MochiKit.DOM.removeElementClass(obj, fromClass); if (res) { MochiKit.DOM.addElementClass(obj, toClass); } return res; }, /** @id MochiKit.DOM.hasElementClass */ hasElementClass: function (element, className/*...*/) { var obj = MochiKit.DOM.getElement(element); if (obj == null) { return false; } var cls = obj.className; if (typeof(cls) != "string") { cls = obj.getAttribute("class"); } if (typeof(cls) != "string") { return false; } var classes = cls.split(" "); for (var i = 1; i < arguments.length; i++) { var good = false; for (var j = 0; j < classes.length; j++) { if (classes[j] == arguments[i]) { good = true; break; } } if (!good) { return false; } } return true; }, /** @id MochiKit.DOM.escapeHTML */ escapeHTML: function (s) { return s.replace(/&/g, "&" ).replace(/"/g, """ ).replace(//g, ">"); }, /** @id MochiKit.DOM.toHTML */ toHTML: function (dom) { return MochiKit.DOM.emitHTML(dom).join(""); }, /** @id MochiKit.DOM.emitHTML */ emitHTML: function (dom, /* optional */lst) { if (typeof(lst) == 'undefined' || lst === null) { lst = []; } // queue is the call stack, we're doing this non-recursively var queue = [dom]; var self = MochiKit.DOM; var escapeHTML = self.escapeHTML; var attributeArray = self.attributeArray; while (queue.length) { dom = queue.pop(); if (typeof(dom) == 'string') { lst.push(dom); } else if (dom.nodeType == 1) { // we're not using higher order stuff here // because safari has heisenbugs.. argh. // // I think it might have something to do with // garbage collection and function calls. lst.push('<' + dom.tagName.toLowerCase()); var attributes = []; var domAttr = attributeArray(dom); for (var i = 0; i < domAttr.length; i++) { var a = domAttr[i]; attributes.push([ " ", a.name, '="', escapeHTML(a.value), '"' ]); } attributes.sort(); for (i = 0; i < attributes.length; i++) { var attrs = attributes[i]; for (var j = 0; j < attrs.length; j++) { lst.push(attrs[j]); } } if (dom.hasChildNodes()) { lst.push(">"); // queue is the FILO call stack, so we put the close tag // on first queue.push(""); var cnodes = dom.childNodes; for (i = cnodes.length - 1; i >= 0; i--) { queue.push(cnodes[i]); } } else { lst.push('/>'); } } else if (dom.nodeType == 3) { lst.push(escapeHTML(dom.nodeValue)); } } return lst; }, /** @id MochiKit.DOM.scrapeText */ scrapeText: function (node, /* optional */asArray) { var rval = []; (function (node) { var cn = node.childNodes; if (cn) { for (var i = 0; i < cn.length; i++) { arguments.callee.call(this, cn[i]); } } var nodeValue = node.nodeValue; if (typeof(nodeValue) == 'string') { rval.push(nodeValue); } })(MochiKit.DOM.getElement(node)); if (asArray) { return rval; } else { return rval.join(""); } }, /** @id MochiKit.DOM.removeEmptyTextNodes */ removeEmptyTextNodes: function (element) { element = MochiKit.DOM.getElement(element); for (var i = 0; i < element.childNodes.length; i++) { var node = element.childNodes[i]; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) { node.parentNode.removeChild(node); } } }, /** @id MochiKit.DOM.getFirstElementByTagAndClassName */ getFirstElementByTagAndClassName: function (tagName, className, /* optional */parent) { var self = MochiKit.DOM; if (typeof(tagName) == 'undefined' || tagName === null) { tagName = '*'; } if (typeof(parent) == 'undefined' || parent === null) { parent = self._document; } parent = self.getElement(parent); if (parent == null) { return null; } var children = (parent.getElementsByTagName(tagName) || self._document.all); if (children.length <= 0) { return null; } else if (typeof(className) == 'undefined' || className === null) { return children[0]; } for (var i = 0; i < children.length; i++) { var child = children[i]; var cls = child.className; if (typeof(cls) != "string") { cls = child.getAttribute("class"); } if (typeof(cls) == "string") { var classNames = cls.split(' '); for (var j = 0; j < classNames.length; j++) { if (classNames[j] == className) { return child; } } } } return null; }, /** @id MochiKit.DOM.getFirstParentByTagAndClassName */ getFirstParentByTagAndClassName: function (elem, tagName, className) { var self = MochiKit.DOM; elem = self.getElement(elem); if (typeof(tagName) == 'undefined' || tagName === null) { tagName = '*'; } else { tagName = tagName.toUpperCase(); } if (typeof(className) == 'undefined' || className === null) { className = null; } if (elem) { elem = elem.parentNode; } while (elem && elem.tagName) { var curTagName = elem.tagName.toUpperCase(); if ((tagName === '*' || tagName == curTagName) && (className === null || self.hasElementClass(elem, className))) { return elem; } elem = elem.parentNode; } return null; }, __new__: function (win) { var m = MochiKit.Base; if (typeof(document) != "undefined") { this._document = document; var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; this._xhtml = (document.documentElement && document.createElementNS && document.documentElement.namespaceURI === kXULNSURI); } else if (MochiKit.MockDOM) { this._document = MochiKit.MockDOM.document; } this._window = win; this.domConverters = new m.AdapterRegistry(); var __tmpElement = this._document.createElement("span"); var attributeArray; if (__tmpElement && __tmpElement.attributes && __tmpElement.attributes.length > 0) { // for braindead browsers (IE) that insert extra junk var filter = m.filter; attributeArray = function (node) { /*** Return an array of attributes for a given node, filtering out attributes that don't belong for that are inserted by "Certain Browsers". ***/ return filter(attributeArray.ignoreAttrFilter, node.attributes); }; attributeArray.ignoreAttr = {}; var attrs = __tmpElement.attributes; var ignoreAttr = attributeArray.ignoreAttr; for (var i = 0; i < attrs.length; i++) { var a = attrs[i]; ignoreAttr[a.name] = a.value; } attributeArray.ignoreAttrFilter = function (a) { return (attributeArray.ignoreAttr[a.name] != a.value); }; attributeArray.compliant = false; attributeArray.renames = { "class": "className", "checked": "defaultChecked", "usemap": "useMap", "for": "htmlFor", "readonly": "readOnly", "colspan": "colSpan", "bgcolor": "bgColor", "cellspacing": "cellSpacing", "cellpadding": "cellPadding" }; } else { attributeArray = function (node) { return node.attributes; }; attributeArray.compliant = true; attributeArray.ignoreAttr = {}; attributeArray.renames = {}; } this.attributeArray = attributeArray; // FIXME: this really belongs in Base, and could probably be cleaner var _deprecated = function(fromModule, arr) { var fromName = arr[0]; var toName = arr[1]; var toModule = toName.split('.')[1]; var str = ''; str += 'if (!MochiKit.' + toModule + ') { throw new Error("'; str += 'This function has been deprecated and depends on MochiKit.'; str += toModule + '.");}'; str += 'return ' + toName + '.apply(this, arguments);'; MochiKit[fromModule][fromName] = new Function(str); } for (var i = 0; i < MochiKit.DOM.DEPRECATED.length; i++) { _deprecated('DOM', MochiKit.DOM.DEPRECATED[i]); } // shorthand for createDOM syntax var createDOMFunc = this.createDOMFunc; /** @id MochiKit.DOM.UL */ this.UL = createDOMFunc("ul"); /** @id MochiKit.DOM.OL */ this.OL = createDOMFunc("ol"); /** @id MochiKit.DOM.LI */ this.LI = createDOMFunc("li"); /** @id MochiKit.DOM.DL */ this.DL = createDOMFunc("dl"); /** @id MochiKit.DOM.DT */ this.DT = createDOMFunc("dt"); /** @id MochiKit.DOM.DD */ this.DD = createDOMFunc("dd"); /** @id MochiKit.DOM.TD */ this.TD = createDOMFunc("td"); /** @id MochiKit.DOM.TR */ this.TR = createDOMFunc("tr"); /** @id MochiKit.DOM.TBODY */ this.TBODY = createDOMFunc("tbody"); /** @id MochiKit.DOM.THEAD */ this.THEAD = createDOMFunc("thead"); /** @id MochiKit.DOM.TFOOT */ this.TFOOT = createDOMFunc("tfoot"); /** @id MochiKit.DOM.TABLE */ this.TABLE = createDOMFunc("table"); /** @id MochiKit.DOM.TH */ this.TH = createDOMFunc("th"); /** @id MochiKit.DOM.INPUT */ this.INPUT = createDOMFunc("input"); /** @id MochiKit.DOM.SPAN */ this.SPAN = createDOMFunc("span"); /** @id MochiKit.DOM.A */ this.A = createDOMFunc("a"); /** @id MochiKit.DOM.DIV */ this.DIV = createDOMFunc("div"); /** @id MochiKit.DOM.IMG */ this.IMG = createDOMFunc("img"); /** @id MochiKit.DOM.BUTTON */ this.BUTTON = createDOMFunc("button"); /** @id MochiKit.DOM.TT */ this.TT = createDOMFunc("tt"); /** @id MochiKit.DOM.PRE */ this.PRE = createDOMFunc("pre"); /** @id MochiKit.DOM.H1 */ this.H1 = createDOMFunc("h1"); /** @id MochiKit.DOM.H2 */ this.H2 = createDOMFunc("h2"); /** @id MochiKit.DOM.H3 */ this.H3 = createDOMFunc("h3"); /** @id MochiKit.DOM.H4 */ this.H4 = createDOMFunc("h4"); /** @id MochiKit.DOM.H5 */ this.H5 = createDOMFunc("h5"); /** @id MochiKit.DOM.H6 */ this.H6 = createDOMFunc("h6"); /** @id MochiKit.DOM.BR */ this.BR = createDOMFunc("br"); /** @id MochiKit.DOM.HR */ this.HR = createDOMFunc("hr"); /** @id MochiKit.DOM.LABEL */ this.LABEL = createDOMFunc("label"); /** @id MochiKit.DOM.TEXTAREA */ this.TEXTAREA = createDOMFunc("textarea"); /** @id MochiKit.DOM.FORM */ this.FORM = createDOMFunc("form"); /** @id MochiKit.DOM.P */ this.P = createDOMFunc("p"); /** @id MochiKit.DOM.SELECT */ this.SELECT = createDOMFunc("select"); /** @id MochiKit.DOM.OPTION */ this.OPTION = createDOMFunc("option"); /** @id MochiKit.DOM.OPTGROUP */ this.OPTGROUP = createDOMFunc("optgroup"); /** @id MochiKit.DOM.LEGEND */ this.LEGEND = createDOMFunc("legend"); /** @id MochiKit.DOM.FIELDSET */ this.FIELDSET = createDOMFunc("fieldset"); /** @id MochiKit.DOM.STRONG */ this.STRONG = createDOMFunc("strong"); /** @id MochiKit.DOM.CANVAS */ this.CANVAS = createDOMFunc("canvas"); /** @id MochiKit.DOM.$ */ this.$ = this.getElement; this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); } }); MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window)); // // XXX: Internet Explorer blows // if (MochiKit.__export__) { withWindow = MochiKit.DOM.withWindow; withDocument = MochiKit.DOM.withDocument; } MochiKit.Base._exportSymbols(this, MochiKit.DOM); MochiKit-1.4.2/lib/MochiKit/Visual.js0000660000175000017500000017524511110666264016374 0ustar scottscott/*** MochiKit.Visual 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito and others. All rights Reserved. ***/ MochiKit.Base._deps('Visual', ['Base', 'DOM', 'Style', 'Color', 'Position']); MochiKit.Visual.NAME = "MochiKit.Visual"; MochiKit.Visual.VERSION = "1.4.2"; MochiKit.Visual.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.Visual.toString = function () { return this.__repr__(); }; MochiKit.Visual._RoundCorners = function (e, options) { e = MochiKit.DOM.getElement(e); this._setOptions(options); if (this.options.__unstable__wrapElement) { e = this._doWrap(e); } var color = this.options.color; var C = MochiKit.Color.Color; if (this.options.color === "fromElement") { color = C.fromBackground(e); } else if (!(color instanceof C)) { color = C.fromString(color); } this.isTransparent = (color.asRGB().a <= 0); var bgColor = this.options.bgColor; if (this.options.bgColor === "fromParent") { bgColor = C.fromBackground(e.offsetParent); } else if (!(bgColor instanceof C)) { bgColor = C.fromString(bgColor); } this._roundCornersImpl(e, color, bgColor); }; MochiKit.Visual._RoundCorners.prototype = { _doWrap: function (e) { var parent = e.parentNode; var doc = MochiKit.DOM.currentDocument(); if (typeof(doc.defaultView) === "undefined" || doc.defaultView === null) { return e; } var style = doc.defaultView.getComputedStyle(e, null); if (typeof(style) === "undefined" || style === null) { return e; } var wrapper = MochiKit.DOM.DIV({"style": { display: "block", // convert padding to margin marginTop: style.getPropertyValue("padding-top"), marginRight: style.getPropertyValue("padding-right"), marginBottom: style.getPropertyValue("padding-bottom"), marginLeft: style.getPropertyValue("padding-left"), // remove padding so the rounding looks right padding: "0px" /* paddingRight: "0px", paddingLeft: "0px" */ }}); wrapper.innerHTML = e.innerHTML; e.innerHTML = ""; e.appendChild(wrapper); return e; }, _roundCornersImpl: function (e, color, bgColor) { if (this.options.border) { this._renderBorder(e, bgColor); } if (this._isTopRounded()) { this._roundTopCorners(e, color, bgColor); } if (this._isBottomRounded()) { this._roundBottomCorners(e, color, bgColor); } }, _renderBorder: function (el, bgColor) { var borderValue = "1px solid " + this._borderColor(bgColor); var borderL = "border-left: " + borderValue; var borderR = "border-right: " + borderValue; var style = "style='" + borderL + ";" + borderR + "'"; el.innerHTML = "
" + el.innerHTML + "
"; }, _roundTopCorners: function (el, color, bgColor) { var corner = this._createCorner(bgColor); for (var i = 0; i < this.options.numSlices; i++) { corner.appendChild( this._createCornerSlice(color, bgColor, i, "top") ); } el.style.paddingTop = 0; el.insertBefore(corner, el.firstChild); }, _roundBottomCorners: function (el, color, bgColor) { var corner = this._createCorner(bgColor); for (var i = (this.options.numSlices - 1); i >= 0; i--) { corner.appendChild( this._createCornerSlice(color, bgColor, i, "bottom") ); } el.style.paddingBottom = 0; el.appendChild(corner); }, _createCorner: function (bgColor) { var dom = MochiKit.DOM; return dom.DIV({style: {backgroundColor: bgColor.toString()}}); }, _createCornerSlice: function (color, bgColor, n, position) { var slice = MochiKit.DOM.SPAN(); var inStyle = slice.style; inStyle.backgroundColor = color.toString(); inStyle.display = "block"; inStyle.height = "1px"; inStyle.overflow = "hidden"; inStyle.fontSize = "1px"; var borderColor = this._borderColor(color, bgColor); if (this.options.border && n === 0) { inStyle.borderTopStyle = "solid"; inStyle.borderTopWidth = "1px"; inStyle.borderLeftWidth = "0px"; inStyle.borderRightWidth = "0px"; inStyle.borderBottomWidth = "0px"; // assumes css compliant box model inStyle.height = "0px"; inStyle.borderColor = borderColor.toString(); } else if (borderColor) { inStyle.borderColor = borderColor.toString(); inStyle.borderStyle = "solid"; inStyle.borderWidth = "0px 1px"; } if (!this.options.compact && (n == (this.options.numSlices - 1))) { inStyle.height = "2px"; } this._setMargin(slice, n, position); this._setBorder(slice, n, position); return slice; }, _setOptions: function (options) { this.options = { corners: "all", color: "fromElement", bgColor: "fromParent", blend: true, border: false, compact: false, __unstable__wrapElement: false }; MochiKit.Base.update(this.options, options); this.options.numSlices = (this.options.compact ? 2 : 4); }, _whichSideTop: function () { var corners = this.options.corners; if (this._hasString(corners, "all", "top")) { return ""; } var has_tl = (corners.indexOf("tl") != -1); var has_tr = (corners.indexOf("tr") != -1); if (has_tl && has_tr) { return ""; } if (has_tl) { return "left"; } if (has_tr) { return "right"; } return ""; }, _whichSideBottom: function () { var corners = this.options.corners; if (this._hasString(corners, "all", "bottom")) { return ""; } var has_bl = (corners.indexOf('bl') != -1); var has_br = (corners.indexOf('br') != -1); if (has_bl && has_br) { return ""; } if (has_bl) { return "left"; } if (has_br) { return "right"; } return ""; }, _borderColor: function (color, bgColor) { if (color == "transparent") { return bgColor; } else if (this.options.border) { return this.options.border; } else if (this.options.blend) { return bgColor.blendedColor(color); } return ""; }, _setMargin: function (el, n, corners) { var marginSize = this._marginSize(n) + "px"; var whichSide = ( corners == "top" ? this._whichSideTop() : this._whichSideBottom() ); var style = el.style; if (whichSide == "left") { style.marginLeft = marginSize; style.marginRight = "0px"; } else if (whichSide == "right") { style.marginRight = marginSize; style.marginLeft = "0px"; } else { style.marginLeft = marginSize; style.marginRight = marginSize; } }, _setBorder: function (el, n, corners) { var borderSize = this._borderSize(n) + "px"; var whichSide = ( corners == "top" ? this._whichSideTop() : this._whichSideBottom() ); var style = el.style; if (whichSide == "left") { style.borderLeftWidth = borderSize; style.borderRightWidth = "0px"; } else if (whichSide == "right") { style.borderRightWidth = borderSize; style.borderLeftWidth = "0px"; } else { style.borderLeftWidth = borderSize; style.borderRightWidth = borderSize; } }, _marginSize: function (n) { if (this.isTransparent) { return 0; } var o = this.options; if (o.compact && o.blend) { var smBlendedMarginSizes = [1, 0]; return smBlendedMarginSizes[n]; } else if (o.compact) { var compactMarginSizes = [2, 1]; return compactMarginSizes[n]; } else if (o.blend) { var blendedMarginSizes = [3, 2, 1, 0]; return blendedMarginSizes[n]; } else { var marginSizes = [5, 3, 2, 1]; return marginSizes[n]; } }, _borderSize: function (n) { var o = this.options; var borderSizes; if (o.compact && (o.blend || this.isTransparent)) { return 1; } else if (o.compact) { borderSizes = [1, 0]; } else if (o.blend) { borderSizes = [2, 1, 1, 1]; } else if (o.border) { borderSizes = [0, 2, 0, 0]; } else if (this.isTransparent) { borderSizes = [5, 3, 2, 1]; } else { return 0; } return borderSizes[n]; }, _hasString: function (str) { for (var i = 1; i< arguments.length; i++) { if (str.indexOf(arguments[i]) != -1) { return true; } } return false; }, _isTopRounded: function () { return this._hasString(this.options.corners, "all", "top", "tl", "tr" ); }, _isBottomRounded: function () { return this._hasString(this.options.corners, "all", "bottom", "bl", "br" ); }, _hasSingleTextChild: function (el) { return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3); } }; /** @id MochiKit.Visual.roundElement */ MochiKit.Visual.roundElement = function (e, options) { new MochiKit.Visual._RoundCorners(e, options); }; /** @id MochiKit.Visual.roundClass */ MochiKit.Visual.roundClass = function (tagName, className, options) { var elements = MochiKit.DOM.getElementsByTagAndClassName( tagName, className ); for (var i = 0; i < elements.length; i++) { MochiKit.Visual.roundElement(elements[i], options); } }; /** @id MochiKit.Visual.tagifyText */ MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) { /*** Change a node text to character in tags. @param tagifyStyle: the style to apply to character nodes, default to 'position: relative'. ***/ tagifyStyle = tagifyStyle || 'position:relative'; if (/MSIE/.test(navigator.userAgent)) { tagifyStyle += ';zoom:1'; } element = MochiKit.DOM.getElement(element); var ma = MochiKit.Base.map; ma(function (child) { if (child.nodeType == 3) { ma(function (character) { element.insertBefore( MochiKit.DOM.SPAN({style: tagifyStyle}, character == ' ' ? String.fromCharCode(160) : character), child); }, child.nodeValue.split('')); MochiKit.DOM.removeElement(child); } }, element.childNodes); }; /** @id MochiKit.Visual.forceRerendering */ MochiKit.Visual.forceRerendering = function (element) { try { element = MochiKit.DOM.getElement(element); var n = document.createTextNode(' '); element.appendChild(n); element.removeChild(n); } catch(e) { } }; /** @id MochiKit.Visual.multiple */ MochiKit.Visual.multiple = function (elements, effect, /* optional */options) { /*** Launch the same effect subsequently on given elements. ***/ options = MochiKit.Base.update({ speed: 0.1, delay: 0.0 }, options); var masterDelay = options.delay; var index = 0; MochiKit.Base.map(function (innerelement) { options.delay = index * options.speed + masterDelay; new effect(innerelement, options); index += 1; }, elements); }; MochiKit.Visual.PAIRS = { 'slide': ['slideDown', 'slideUp'], 'blind': ['blindDown', 'blindUp'], 'appear': ['appear', 'fade'], 'size': ['grow', 'shrink'] }; /** @id MochiKit.Visual.toggle */ MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) { /*** Toggle an item between two state depending of its visibility, making a effect between these states. Default effect is 'appear', can be 'slide' or 'blind'. ***/ element = MochiKit.DOM.getElement(element); effect = (effect || 'appear').toLowerCase(); options = MochiKit.Base.update({ queue: {position: 'end', scope: (element.id || 'global'), limit: 1} }, options); var v = MochiKit.Visual; v[MochiKit.Style.getStyle(element, 'display') != 'none' ? v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options); }; /*** Transitions: define functions calculating variations depending of a position. ***/ MochiKit.Visual.Transitions = {}; /** @id MochiKit.Visual.Transitions.linear */ MochiKit.Visual.Transitions.linear = function (pos) { return pos; }; /** @id MochiKit.Visual.Transitions.sinoidal */ MochiKit.Visual.Transitions.sinoidal = function (pos) { return 0.5 - Math.cos(pos*Math.PI)/2; }; /** @id MochiKit.Visual.Transitions.reverse */ MochiKit.Visual.Transitions.reverse = function (pos) { return 1 - pos; }; /** @id MochiKit.Visual.Transitions.flicker */ MochiKit.Visual.Transitions.flicker = function (pos) { return 0.25 - Math.cos(pos*Math.PI)/4 + Math.random()/2; }; /** @id MochiKit.Visual.Transitions.wobble */ MochiKit.Visual.Transitions.wobble = function (pos) { return 0.5 - Math.cos(9*pos*Math.PI)/2; }; /** @id MochiKit.Visual.Transitions.pulse */ MochiKit.Visual.Transitions.pulse = function (pos, pulses) { if (pulses) { pos *= 2 * pulses; } else { pos *= 10; } var decimals = pos - Math.floor(pos); return (Math.floor(pos) % 2 == 0) ? decimals : 1 - decimals; }; /** @id MochiKit.Visual.Transitions.parabolic */ MochiKit.Visual.Transitions.parabolic = function (pos) { return pos * pos; }; /** @id MochiKit.Visual.Transitions.none */ MochiKit.Visual.Transitions.none = function (pos) { return 0; }; /** @id MochiKit.Visual.Transitions.full */ MochiKit.Visual.Transitions.full = function (pos) { return 1; }; /*** Core effects ***/ MochiKit.Visual.ScopedQueue = function () { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(); } this.__init__(); }; MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, { __init__: function () { this.effects = []; this.interval = null; }, /** @id MochiKit.Visual.ScopedQueue.prototype.add */ add: function (effect) { var timestamp = new Date().getTime(); var position = (typeof(effect.options.queue) == 'string') ? effect.options.queue : effect.options.queue.position; var ma = MochiKit.Base.map; switch (position) { case 'front': // move unstarted effects after this effect ma(function (e) { if (e.state == 'idle') { e.startOn += effect.finishOn; e.finishOn += effect.finishOn; } }, this.effects); break; case 'end': var finish; // start effect after last queued effect has finished ma(function (e) { var i = e.finishOn; if (i >= (finish || i)) { finish = i; } }, this.effects); timestamp = finish || timestamp; break; case 'break': ma(function (e) { e.finalize(); }, this.effects); 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 = this.startLoop(MochiKit.Base.bind(this.loop, this), 40); } }, /** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */ startLoop: function (func, interval) { return setInterval(func, interval); }, /** @id MochiKit.Visual.ScopedQueue.prototype.remove */ remove: function (effect) { this.effects = MochiKit.Base.filter(function (e) { return e != effect; }, this.effects); if (!this.effects.length) { this.stopLoop(this.interval); this.interval = null; } }, /** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */ stopLoop: function (interval) { clearInterval(interval); }, /** @id MochiKit.Visual.ScopedQueue.prototype.loop */ loop: function () { var timePos = new Date().getTime(); MochiKit.Base.map(function (effect) { effect.loop(timePos); }, this.effects); } }); MochiKit.Visual.Queues = { instances: {}, get: function (queueName) { if (typeof(queueName) != 'string') { return queueName; } if (!this.instances[queueName]) { this.instances[queueName] = new MochiKit.Visual.ScopedQueue(); } return this.instances[queueName]; } }; MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global'); MochiKit.Visual.DefaultOptions = { transition: MochiKit.Visual.Transitions.sinoidal, duration: 1.0, // seconds fps: 25.0, // max. 25fps due to MochiKit.Visual.Queue implementation sync: false, // true for combining from: 0.0, to: 1.0, delay: 0.0, queue: 'parallel' }; MochiKit.Visual.Base = function () {}; MochiKit.Visual.Base.prototype = { /*** Basic class for all Effects. Define a looping mechanism called for each step of an effect. Don't instantiate it, only subclass it. ***/ __class__ : MochiKit.Visual.Base, /** @id MochiKit.Visual.Base.prototype.start */ start: function (options) { var v = MochiKit.Visual; this.options = MochiKit.Base.setdefault(options, v.DefaultOptions); this.currentFrame = 0; this.state = 'idle'; this.startOn = this.options.delay*1000; this.finishOn = this.startOn + (this.options.duration*1000); this.event('beforeStart'); if (!this.options.sync) { v.Queues.get(typeof(this.options.queue) == 'string' ? 'global' : this.options.queue.scope).add(this); } }, /** @id MochiKit.Visual.Base.prototype.loop */ loop: function (timePos) { if (timePos >= this.startOn) { if (timePos >= this.finishOn) { return this.finalize(); } var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); var frame = Math.round(pos * this.options.fps * this.options.duration); if (frame > this.currentFrame) { this.render(pos); this.currentFrame = frame; } } }, /** @id MochiKit.Visual.Base.prototype.render */ render: function (pos) { if (this.state == 'idle') { this.state = 'running'; this.event('beforeSetup'); this.setup(); this.event('afterSetup'); } if (this.state == 'running') { if (this.options.transition) { pos = this.options.transition(pos); } pos *= (this.options.to - this.options.from); pos += this.options.from; this.event('beforeUpdate'); this.update(pos); this.event('afterUpdate'); } }, /** @id MochiKit.Visual.Base.prototype.cancel */ cancel: function () { if (!this.options.sync) { MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ? 'global' : this.options.queue.scope).remove(this); } this.state = 'finished'; }, /** @id MochiKit.Visual.Base.prototype.finalize */ finalize: function () { this.render(1.0); this.cancel(); this.event('beforeFinish'); this.finish(); this.event('afterFinish'); }, setup: function () { }, finish: function () { }, update: function (position) { }, /** @id MochiKit.Visual.Base.prototype.event */ event: function (eventName) { if (this.options[eventName + 'Internal']) { this.options[eventName + 'Internal'](this); } if (this.options[eventName]) { this.options[eventName](this); } }, /** @id MochiKit.Visual.Base.prototype.repr */ repr: function () { return '[' + this.__class__.NAME + ', options:' + MochiKit.Base.repr(this.options) + ']'; } }; /** @id MochiKit.Visual.Parallel */ MochiKit.Visual.Parallel = function (effects, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(effects, options); } this.__init__(effects, options); }; MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, { /*** Run multiple effects at the same time. ***/ __class__ : MochiKit.Visual.Parallel, __init__: function (effects, options) { this.effects = effects || []; this.start(options); }, /** @id MochiKit.Visual.Parallel.prototype.update */ update: function (position) { MochiKit.Base.map(function (effect) { effect.render(position); }, this.effects); }, /** @id MochiKit.Visual.Parallel.prototype.finish */ finish: function () { MochiKit.Base.map(function (effect) { effect.finalize(); }, this.effects); } }); /** @id MochiKit.Visual.Sequence */ MochiKit.Visual.Sequence = function (effects, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(effects, options); } this.__init__(effects, options); }; MochiKit.Visual.Sequence.prototype = new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Sequence.prototype, { __class__ : MochiKit.Visual.Sequence, __init__: function (effects, options) { var defs = { transition: MochiKit.Visual.Transitions.linear, duration: 0 }; this.effects = effects || []; MochiKit.Base.map(function (effect) { defs.duration += effect.options.duration; }, this.effects); MochiKit.Base.setdefault(options, defs); this.start(options); }, /** @id MochiKit.Visual.Sequence.prototype.update */ update: function (position) { var time = position * this.options.duration; for (var i = 0; i < this.effects.length; i++) { var effect = this.effects[i]; if (time <= effect.options.duration) { effect.render(time / effect.options.duration); break; } else { time -= effect.options.duration; } } }, /** @id MochiKit.Visual.Sequence.prototype.finish */ finish: function () { MochiKit.Base.map(function (effect) { effect.finalize(); }, this.effects); } }); /** @id MochiKit.Visual.Opacity */ MochiKit.Visual.Opacity = function (element, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(element, options); } this.__init__(element, options); }; MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, { /*** Change the opacity of an element. @param options: 'from' and 'to' change the starting and ending opacities. Must be between 0.0 and 1.0. Default to current opacity and 1.0. ***/ __class__ : MochiKit.Visual.Opacity, __init__: function (element, /* optional */options) { var b = MochiKit.Base; var s = MochiKit.Style; this.element = MochiKit.DOM.getElement(element); // make this work on IE on elements without 'layout' if (this.element.currentStyle && (!this.element.currentStyle.hasLayout)) { s.setStyle(this.element, {zoom: 1}); } options = b.update({ from: s.getStyle(this.element, 'opacity') || 0.0, to: 1.0 }, options); this.start(options); }, /** @id MochiKit.Visual.Opacity.prototype.update */ update: function (position) { MochiKit.Style.setStyle(this.element, {'opacity': position}); } }); /** @id MochiKit.Visual.Move.prototype */ MochiKit.Visual.Move = function (element, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(element, options); } this.__init__(element, options); }; MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Move.prototype, { /*** Move an element between its current position to a defined position @param options: 'x' and 'y' for final positions, default to 0, 0. ***/ __class__ : MochiKit.Visual.Move, __init__: function (element, /* optional */options) { this.element = MochiKit.DOM.getElement(element); options = MochiKit.Base.update({ x: 0, y: 0, mode: 'relative' }, options); this.start(options); }, /** @id MochiKit.Visual.Move.prototype.setup */ setup: function () { // Bug in Opera: Opera returns the 'real' position of a static element // or relative element that does not have top/left explicitly set. // ==> Always set top and left for position relative elements in your // stylesheets (to 0 if you do not need them) MochiKit.Style.makePositioned(this.element); var s = this.element.style; var originalVisibility = s.visibility; var originalDisplay = s.display; if (originalDisplay == 'none') { s.visibility = 'hidden'; s.display = ''; } this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0'); this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0'); if (this.options.mode == 'absolute') { // absolute movement, so we need to calc deltaX and deltaY this.options.x -= this.originalLeft; this.options.y -= this.originalTop; } if (originalDisplay == 'none') { s.visibility = originalVisibility; s.display = originalDisplay; } }, /** @id MochiKit.Visual.Move.prototype.update */ update: function (position) { MochiKit.Style.setStyle(this.element, { left: Math.round(this.options.x * position + this.originalLeft) + 'px', top: Math.round(this.options.y * position + this.originalTop) + 'px' }); } }); /** @id MochiKit.Visual.Scale */ MochiKit.Visual.Scale = function (element, percent, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(element, percent, options); } this.__init__(element, percent, options); }; MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Scale.prototype, { /*** Change the size of an element. @param percent: final_size = percent*original_size @param options: several options changing scale behaviour ***/ __class__ : MochiKit.Visual.Scale, __init__: function (element, percent, /* optional */options) { this.element = MochiKit.DOM.getElement(element); options = MochiKit.Base.update({ scaleX: true, scaleY: true, scaleContent: true, scaleFromCenter: false, scaleMode: 'box', // 'box' or 'contents' or {} with provided values scaleFrom: 100.0, scaleTo: percent }, options); this.start(options); }, /** @id MochiKit.Visual.Scale.prototype.setup */ setup: function () { this.restoreAfterFinish = this.options.restoreAfterFinish || false; this.elementPositioning = MochiKit.Style.getStyle(this.element, 'position'); var ma = MochiKit.Base.map; var b = MochiKit.Base.bind; this.originalStyle = {}; ma(b(function (k) { this.originalStyle[k] = this.element.style[k]; }, this), ['top', 'left', 'width', 'height', 'fontSize']); this.originalTop = this.element.offsetTop; this.originalLeft = this.element.offsetLeft; var fontSize = MochiKit.Style.getStyle(this.element, 'font-size') || '100%'; ma(b(function (fontSizeType) { if (fontSize.indexOf(fontSizeType) > 0) { this.fontSize = parseFloat(fontSize); this.fontSizeType = fontSizeType; } }, this), ['em', 'px', '%']); this.factor = (this.options.scaleTo - this.options.scaleFrom)/100; if (/^content/.test(this.options.scaleMode)) { this.dims = [this.element.scrollHeight, this.element.scrollWidth]; } else if (this.options.scaleMode == 'box') { this.dims = [this.element.offsetHeight, this.element.offsetWidth]; } else { this.dims = [this.options.scaleMode.originalHeight, this.options.scaleMode.originalWidth]; } }, /** @id MochiKit.Visual.Scale.prototype.update */ update: function (position) { var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position); if (this.options.scaleContent && this.fontSize) { MochiKit.Style.setStyle(this.element, { fontSize: this.fontSize * currentScale + this.fontSizeType }); } this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale); }, /** @id MochiKit.Visual.Scale.prototype.finish */ finish: function () { if (this.restoreAfterFinish) { MochiKit.Style.setStyle(this.element, this.originalStyle); } }, /** @id MochiKit.Visual.Scale.prototype.setDimensions */ setDimensions: function (height, width) { var d = {}; var r = Math.round; if (/MSIE/.test(navigator.userAgent)) { r = Math.ceil; } if (this.options.scaleX) { d.width = r(width) + 'px'; } if (this.options.scaleY) { d.height = r(height) + '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'; } } } MochiKit.Style.setStyle(this.element, d); } }); /** @id MochiKit.Visual.Highlight */ MochiKit.Visual.Highlight = function (element, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(element, options); } this.__init__(element, options); }; MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, { /*** Highlight an item of the page. @param options: 'startcolor' for choosing highlighting color, default to '#ffff99'. ***/ __class__ : MochiKit.Visual.Highlight, __init__: function (element, /* optional */options) { this.element = MochiKit.DOM.getElement(element); options = MochiKit.Base.update({ startcolor: '#ffff99' }, options); this.start(options); }, /** @id MochiKit.Visual.Highlight.prototype.setup */ setup: function () { var b = MochiKit.Base; var s = MochiKit.Style; // Prevent executing on elements not in the layout flow if (s.getStyle(this.element, 'display') == 'none') { this.cancel(); return; } // Disable background image during the effect this.oldStyle = { backgroundImage: s.getStyle(this.element, 'background-image') }; s.setStyle(this.element, { backgroundImage: 'none' }); if (!this.options.endcolor) { this.options.endcolor = MochiKit.Color.Color.fromBackground(this.element).toHexString(); } if (b.isUndefinedOrNull(this.options.restorecolor)) { this.options.restorecolor = s.getStyle(this.element, 'background-color'); } // init color calculations this._base = b.map(b.bind(function (i) { return parseInt( this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16); }, this), [0, 1, 2]); this._delta = b.map(b.bind(function (i) { return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16) - this._base[i]; }, this), [0, 1, 2]); }, /** @id MochiKit.Visual.Highlight.prototype.update */ update: function (position) { var m = '#'; MochiKit.Base.map(MochiKit.Base.bind(function (i) { m += MochiKit.Color.toColorPart(Math.round(this._base[i] + this._delta[i]*position)); }, this), [0, 1, 2]); MochiKit.Style.setStyle(this.element, { backgroundColor: m }); }, /** @id MochiKit.Visual.Highlight.prototype.finish */ finish: function () { MochiKit.Style.setStyle(this.element, MochiKit.Base.update(this.oldStyle, { backgroundColor: this.options.restorecolor })); } }); /** @id MochiKit.Visual.ScrollTo */ MochiKit.Visual.ScrollTo = function (element, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(element, options); } this.__init__(element, options); }; MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, { /*** Scroll to an element in the page. ***/ __class__ : MochiKit.Visual.ScrollTo, __init__: function (element, /* optional */options) { this.element = MochiKit.DOM.getElement(element); this.start(options); }, /** @id MochiKit.Visual.ScrollTo.prototype.setup */ setup: function () { var p = MochiKit.Position; p.prepare(); var offsets = p.cumulativeOffset(this.element); if (this.options.offset) { offsets.y += this.options.offset; } var max; if (window.innerHeight) { max = window.innerHeight - window.height; } else if (document.documentElement && document.documentElement.clientHeight) { max = document.documentElement.clientHeight - document.body.scrollHeight; } else if (document.body) { max = document.body.clientHeight - document.body.scrollHeight; } this.scrollStart = p.windowOffset.y; this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart; }, /** @id MochiKit.Visual.ScrollTo.prototype.update */ update: function (position) { var p = MochiKit.Position; p.prepare(); window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta)); } }); MochiKit.Visual.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; MochiKit.Visual.Morph = function (element, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(element, options); } this.__init__(element, options); }; MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base(); MochiKit.Base.update(MochiKit.Visual.Morph.prototype, { /*** Morph effect: make a transformation from current style to the given style, automatically making a transition between the two. ***/ __class__ : MochiKit.Visual.Morph, __init__: function (element, /* optional */options) { this.element = MochiKit.DOM.getElement(element); this.start(options); }, /** @id MochiKit.Visual.Morph.prototype.setup */ setup: function () { var b = MochiKit.Base; var style = this.options.style; this.styleStart = {}; this.styleEnd = {}; this.units = {}; var value, unit; for (var s in style) { value = style[s]; s = b.camelize(s); if (MochiKit.Visual.CSS_LENGTH.test(value)) { var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); value = parseFloat(components[1]); unit = (components.length == 3) ? components[2] : null; this.styleEnd[s] = value; this.units[s] = unit; value = MochiKit.Style.getStyle(this.element, s); components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); value = parseFloat(components[1]); this.styleStart[s] = value; } else if (/[Cc]olor$/.test(s)) { var c = MochiKit.Color.Color; value = c.fromString(value); if (value) { this.units[s] = "color"; this.styleEnd[s] = value.toHexString(); value = MochiKit.Style.getStyle(this.element, s); this.styleStart[s] = c.fromString(value).toHexString(); this.styleStart[s] = b.map(b.bind(function (i) { return parseInt( this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16); }, this), [0, 1, 2]); this.styleEnd[s] = b.map(b.bind(function (i) { return parseInt( this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16); }, this), [0, 1, 2]); } } else { // For non-length & non-color properties, we just set the value this.element.style[s] = value; } } }, /** @id MochiKit.Visual.Morph.prototype.update */ update: function (position) { var value; for (var s in this.styleStart) { if (this.units[s] == "color") { var m = '#'; var start = this.styleStart[s]; var end = this.styleEnd[s]; MochiKit.Base.map(MochiKit.Base.bind(function (i) { m += MochiKit.Color.toColorPart(Math.round(start[i] + (end[i] - start[i])*position)); }, this), [0, 1, 2]); this.element.style[s] = m; } else { value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s]; this.element.style[s] = value; } } } }); /*** Combination effects. ***/ /** @id MochiKit.Visual.fade */ MochiKit.Visual.fade = function (element, /* optional */ options) { /*** Fade a given element: change its opacity and hide it in the end. @param options: 'to' and 'from' to change opacity. ***/ var s = MochiKit.Style; var oldOpacity = s.getStyle(element, 'opacity'); options = MochiKit.Base.update({ from: s.getStyle(element, 'opacity') || 1.0, to: 0.0, afterFinishInternal: function (effect) { if (effect.options.to !== 0) { return; } s.hideElement(effect.element); s.setStyle(effect.element, {'opacity': oldOpacity}); } }, options); return new MochiKit.Visual.Opacity(element, options); }; /** @id MochiKit.Visual.appear */ MochiKit.Visual.appear = function (element, /* optional */ options) { /*** Make an element appear. @param options: 'to' and 'from' to change opacity. ***/ var s = MochiKit.Style; var v = MochiKit.Visual; options = MochiKit.Base.update({ from: (s.getStyle(element, 'display') == 'none' ? 0.0 : s.getStyle(element, 'opacity') || 0.0), to: 1.0, // force Safari to render floated elements properly afterFinishInternal: function (effect) { v.forceRerendering(effect.element); }, beforeSetupInternal: function (effect) { s.setStyle(effect.element, {'opacity': effect.options.from}); s.showElement(effect.element); } }, options); return new v.Opacity(element, options); }; /** @id MochiKit.Visual.puff */ MochiKit.Visual.puff = function (element, /* optional */ options) { /*** 'Puff' an element: grow it to double size, fading it and make it hidden. ***/ var s = MochiKit.Style; var v = MochiKit.Visual; element = MochiKit.DOM.getElement(element); var elementDimensions = MochiKit.Style.getElementDimensions(element, true); var oldStyle = { position: s.getStyle(element, 'position'), top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height, opacity: s.getStyle(element, 'opacity') }; options = MochiKit.Base.update({ beforeSetupInternal: function (effect) { MochiKit.Position.absolutize(effect.effects[0].element); }, afterFinishInternal: function (effect) { s.hideElement(effect.effects[0].element); s.setStyle(effect.effects[0].element, oldStyle); }, scaleContent: true, scaleFromCenter: true }, options); return new v.Parallel( [new v.Scale(element, 200, {sync: true, scaleFromCenter: options.scaleFromCenter, scaleMode: {originalHeight: elementDimensions.h, originalWidth: elementDimensions.w}, scaleContent: options.scaleContent, restoreAfterFinish: true}), new v.Opacity(element, {sync: true, to: 0.0 })], options); }; /** @id MochiKit.Visual.blindUp */ MochiKit.Visual.blindUp = function (element, /* optional */ options) { /*** Blind an element up: change its vertical size to 0. ***/ var d = MochiKit.DOM; var s = MochiKit.Style; element = d.getElement(element); var elementDimensions = s.getElementDimensions(element, true); var elemClip = s.makeClipping(element); options = MochiKit.Base.update({ scaleContent: false, scaleX: false, scaleMode: {originalHeight: elementDimensions.h, originalWidth: elementDimensions.w}, restoreAfterFinish: true, afterFinishInternal: function (effect) { s.hideElement(effect.element); s.undoClipping(effect.element, elemClip); } }, options); return new MochiKit.Visual.Scale(element, 0, options); }; /** @id MochiKit.Visual.blindDown */ MochiKit.Visual.blindDown = function (element, /* optional */ options) { /*** Blind an element down: restore its vertical size. ***/ var d = MochiKit.DOM; var s = MochiKit.Style; element = d.getElement(element); var elementDimensions = s.getElementDimensions(element, true); var elemClip; options = MochiKit.Base.update({ scaleContent: false, scaleX: false, scaleFrom: 0, scaleMode: {originalHeight: elementDimensions.h, originalWidth: elementDimensions.w}, restoreAfterFinish: true, afterSetupInternal: function (effect) { elemClip = s.makeClipping(effect.element); s.setStyle(effect.element, {height: '0px'}); s.showElement(effect.element); }, afterFinishInternal: function (effect) { s.undoClipping(effect.element, elemClip); } }, options); return new MochiKit.Visual.Scale(element, 100, options); }; /** @id MochiKit.Visual.switchOff */ MochiKit.Visual.switchOff = function (element, /* optional */ options) { /*** Apply a switch-off-like effect. ***/ var d = MochiKit.DOM; var s = MochiKit.Style; element = d.getElement(element); var elementDimensions = s.getElementDimensions(element, true); var oldOpacity = s.getStyle(element, 'opacity'); var elemClip; options = MochiKit.Base.update({ duration: 0.7, restoreAfterFinish: true, beforeSetupInternal: function (effect) { s.makePositioned(element); elemClip = s.makeClipping(element); }, afterFinishInternal: function (effect) { s.hideElement(element); s.undoClipping(element, elemClip); s.undoPositioned(element); s.setStyle(element, {'opacity': oldOpacity}); } }, options); var v = MochiKit.Visual; return new v.Sequence( [new v.appear(element, { sync: true, duration: 0.57 * options.duration, from: 0, transition: v.Transitions.flicker }), new v.Scale(element, 1, { sync: true, duration: 0.43 * options.duration, scaleFromCenter: true, scaleX: false, scaleMode: {originalHeight: elementDimensions.h, originalWidth: elementDimensions.w}, scaleContent: false, restoreAfterFinish: true })], options); }; /** @id MochiKit.Visual.dropOut */ MochiKit.Visual.dropOut = function (element, /* optional */ options) { /*** Make an element fall and disappear. ***/ var d = MochiKit.DOM; var s = MochiKit.Style; element = d.getElement(element); var oldStyle = { top: s.getStyle(element, 'top'), left: s.getStyle(element, 'left'), opacity: s.getStyle(element, 'opacity') }; options = MochiKit.Base.update({ duration: 0.5, distance: 100, beforeSetupInternal: function (effect) { s.makePositioned(effect.effects[0].element); }, afterFinishInternal: function (effect) { s.hideElement(effect.effects[0].element); s.undoPositioned(effect.effects[0].element); s.setStyle(effect.effects[0].element, oldStyle); } }, options); var v = MochiKit.Visual; return new v.Parallel( [new v.Move(element, {x: 0, y: options.distance, sync: true}), new v.Opacity(element, {sync: true, to: 0.0})], options); }; /** @id MochiKit.Visual.shake */ MochiKit.Visual.shake = function (element, /* optional */ options) { /*** Move an element from left to right several times. ***/ var d = MochiKit.DOM; var v = MochiKit.Visual; var s = MochiKit.Style; element = d.getElement(element); var oldStyle = { top: s.getStyle(element, 'top'), left: s.getStyle(element, 'left') }; options = MochiKit.Base.update({ duration: 0.5, afterFinishInternal: function (effect) { s.undoPositioned(element); s.setStyle(element, oldStyle); } }, options); return new v.Sequence( [new v.Move(element, { sync: true, duration: 0.1 * options.duration, x: 20, y: 0 }), new v.Move(element, { sync: true, duration: 0.2 * options.duration, x: -40, y: 0 }), new v.Move(element, { sync: true, duration: 0.2 * options.duration, x: 40, y: 0 }), new v.Move(element, { sync: true, duration: 0.2 * options.duration, x: -40, y: 0 }), new v.Move(element, { sync: true, duration: 0.2 * options.duration, x: 40, y: 0 }), new v.Move(element, { sync: true, duration: 0.1 * options.duration, x: -20, y: 0 })], options); }; /** @id MochiKit.Visual.slideDown */ MochiKit.Visual.slideDown = function (element, /* optional */ options) { /*** Slide an element down. It needs to have the content of the element wrapped in a container element with fixed height. ***/ var d = MochiKit.DOM; var b = MochiKit.Base; var s = MochiKit.Style; element = d.getElement(element); if (!element.firstChild) { throw new Error("MochiKit.Visual.slideDown must be used on a element with a child"); } d.removeEmptyTextNodes(element); var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0; var elementDimensions = s.getElementDimensions(element, true); var elemClip; options = b.update({ scaleContent: false, scaleX: false, scaleFrom: 0, scaleMode: {originalHeight: elementDimensions.h, originalWidth: elementDimensions.w}, restoreAfterFinish: true, afterSetupInternal: function (effect) { s.makePositioned(effect.element); s.makePositioned(effect.element.firstChild); if (/Opera/.test(navigator.userAgent)) { s.setStyle(effect.element, {top: ''}); } elemClip = s.makeClipping(effect.element); s.setStyle(effect.element, {height: '0px'}); s.showElement(effect.element); }, afterUpdateInternal: function (effect) { var elementDimensions = s.getElementDimensions(effect.element, true); s.setStyle(effect.element.firstChild, {bottom: (effect.dims[0] - elementDimensions.h) + 'px'}); }, afterFinishInternal: function (effect) { s.undoClipping(effect.element, elemClip); // IE will crash if child is undoPositioned first if (/MSIE/.test(navigator.userAgent)) { s.undoPositioned(effect.element); s.undoPositioned(effect.element.firstChild); } else { s.undoPositioned(effect.element.firstChild); s.undoPositioned(effect.element); } s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); } }, options); return new MochiKit.Visual.Scale(element, 100, options); }; /** @id MochiKit.Visual.slideUp */ MochiKit.Visual.slideUp = function (element, /* optional */ options) { /*** Slide an element up. It needs to have the content of the element wrapped in a container element with fixed height. ***/ var d = MochiKit.DOM; var b = MochiKit.Base; var s = MochiKit.Style; element = d.getElement(element); if (!element.firstChild) { throw new Error("MochiKit.Visual.slideUp must be used on a element with a child"); } d.removeEmptyTextNodes(element); var oldInnerBottom = s.getStyle(element.firstChild, 'bottom'); var elementDimensions = s.getElementDimensions(element, true); var elemClip; options = b.update({ scaleContent: false, scaleX: false, scaleMode: {originalHeight: elementDimensions.h, originalWidth: elementDimensions.w}, scaleFrom: 100, restoreAfterFinish: true, beforeStartInternal: function (effect) { s.makePositioned(effect.element); s.makePositioned(effect.element.firstChild); if (/Opera/.test(navigator.userAgent)) { s.setStyle(effect.element, {top: ''}); } elemClip = s.makeClipping(effect.element); s.showElement(effect.element); }, afterUpdateInternal: function (effect) { var elementDimensions = s.getElementDimensions(effect.element, true); s.setStyle(effect.element.firstChild, {bottom: (effect.dims[0] - elementDimensions.h) + 'px'}); }, afterFinishInternal: function (effect) { s.hideElement(effect.element); s.undoClipping(effect.element, elemClip); s.undoPositioned(effect.element.firstChild); s.undoPositioned(effect.element); s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom}); } }, options); return new MochiKit.Visual.Scale(element, 0, options); }; // Bug in opera makes the TD containing this element expand for a instance // after finish /** @id MochiKit.Visual.squish */ MochiKit.Visual.squish = function (element, /* optional */ options) { /*** Reduce an element and make it disappear. ***/ var d = MochiKit.DOM; var b = MochiKit.Base; var s = MochiKit.Style; var elementDimensions = s.getElementDimensions(element, true); var elemClip; options = b.update({ restoreAfterFinish: true, scaleMode: {originalHeight: elementDimensions.w, originalWidth: elementDimensions.h}, beforeSetupInternal: function (effect) { elemClip = s.makeClipping(effect.element); }, afterFinishInternal: function (effect) { s.hideElement(effect.element); s.undoClipping(effect.element, elemClip); } }, options); return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options); }; /** @id MochiKit.Visual.grow */ MochiKit.Visual.grow = function (element, /* optional */ options) { /*** Grow an element to its original size. Make it zero-sized before if necessary. ***/ var d = MochiKit.DOM; var v = MochiKit.Visual; var s = MochiKit.Style; element = d.getElement(element); options = MochiKit.Base.update({ direction: 'center', moveTransition: v.Transitions.sinoidal, scaleTransition: v.Transitions.sinoidal, opacityTransition: v.Transitions.full, scaleContent: true, scaleFromCenter: false }, options); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: s.getStyle(element, 'opacity') }; var dims = s.getElementDimensions(element, true); var initialMoveX, initialMoveY; var moveX, moveY; switch (options.direction) { case 'top-left': initialMoveX = initialMoveY = moveX = moveY = 0; break; case 'top-right': initialMoveX = dims.w; initialMoveY = moveY = 0; moveX = -dims.w; break; case 'bottom-left': initialMoveX = moveX = 0; initialMoveY = dims.h; moveY = -dims.h; break; case 'bottom-right': initialMoveX = dims.w; initialMoveY = dims.h; moveX = -dims.w; moveY = -dims.h; break; case 'center': initialMoveX = dims.w / 2; initialMoveY = dims.h / 2; moveX = -dims.w / 2; moveY = -dims.h / 2; break; } var optionsParallel = MochiKit.Base.update({ beforeSetupInternal: function (effect) { s.setStyle(effect.effects[0].element, {height: '0px'}); s.showElement(effect.effects[0].element); }, afterFinishInternal: function (effect) { s.undoClipping(effect.effects[0].element); s.undoPositioned(effect.effects[0].element); s.setStyle(effect.effects[0].element, oldStyle); } }, options); return new v.Move(element, { x: initialMoveX, y: initialMoveY, duration: 0.01, beforeSetupInternal: function (effect) { s.hideElement(effect.element); s.makeClipping(effect.element); s.makePositioned(effect.element); }, afterFinishInternal: function (effect) { new v.Parallel( [new v.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }), new v.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }), new v.Scale(effect.element, 100, { scaleMode: {originalHeight: dims.h, originalWidth: dims.w}, sync: true, scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0, transition: options.scaleTransition, scaleContent: options.scaleContent, scaleFromCenter: options.scaleFromCenter, restoreAfterFinish: true }) ], optionsParallel ); } }); }; /** @id MochiKit.Visual.shrink */ MochiKit.Visual.shrink = function (element, /* optional */ options) { /*** Shrink an element and make it disappear. ***/ var d = MochiKit.DOM; var v = MochiKit.Visual; var s = MochiKit.Style; element = d.getElement(element); options = MochiKit.Base.update({ direction: 'center', moveTransition: v.Transitions.sinoidal, scaleTransition: v.Transitions.sinoidal, opacityTransition: v.Transitions.none, scaleContent: true, scaleFromCenter: false }, options); var oldStyle = { top: element.style.top, left: element.style.left, height: element.style.height, width: element.style.width, opacity: s.getStyle(element, 'opacity') }; var dims = s.getElementDimensions(element, true); var moveX, moveY; switch (options.direction) { case 'top-left': moveX = moveY = 0; break; case 'top-right': moveX = dims.w; moveY = 0; break; case 'bottom-left': moveX = 0; moveY = dims.h; break; case 'bottom-right': moveX = dims.w; moveY = dims.h; break; case 'center': moveX = dims.w / 2; moveY = dims.h / 2; break; } var elemClip; var optionsParallel = MochiKit.Base.update({ beforeStartInternal: function (effect) { s.makePositioned(effect.effects[0].element); elemClip = s.makeClipping(effect.effects[0].element); }, afterFinishInternal: function (effect) { s.hideElement(effect.effects[0].element); s.undoClipping(effect.effects[0].element, elemClip); s.undoPositioned(effect.effects[0].element); s.setStyle(effect.effects[0].element, oldStyle); } }, options); return new v.Parallel( [new v.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }), new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, { scaleMode: {originalHeight: dims.h, originalWidth: dims.w}, sync: true, transition: options.scaleTransition, scaleContent: options.scaleContent, scaleFromCenter: options.scaleFromCenter, restoreAfterFinish: true }), new v.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }) ], optionsParallel ); }; /** @id MochiKit.Visual.pulsate */ MochiKit.Visual.pulsate = function (element, /* optional */ options) { /*** Pulse an element between appear/fade. ***/ var d = MochiKit.DOM; var v = MochiKit.Visual; var b = MochiKit.Base; var oldOpacity = MochiKit.Style.getStyle(element, 'opacity'); options = b.update({ duration: 3.0, from: 0, afterFinishInternal: function (effect) { MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity}); } }, options); var transition = options.transition || v.Transitions.sinoidal; options.transition = function (pos) { return transition(1 - v.Transitions.pulse(pos, options.pulses)); }; return new v.Opacity(element, options); }; /** @id MochiKit.Visual.fold */ MochiKit.Visual.fold = function (element, /* optional */ options) { /*** Fold an element, first vertically, then horizontally. ***/ var d = MochiKit.DOM; var v = MochiKit.Visual; var s = MochiKit.Style; element = d.getElement(element); var elementDimensions = s.getElementDimensions(element, true); var oldStyle = { top: element.style.top, left: element.style.left, width: element.style.width, height: element.style.height }; var elemClip = s.makeClipping(element); options = MochiKit.Base.update({ scaleContent: false, scaleX: false, scaleMode: {originalHeight: elementDimensions.h, originalWidth: elementDimensions.w}, afterFinishInternal: function (effect) { new v.Scale(element, 1, { scaleContent: false, scaleY: false, scaleMode: {originalHeight: elementDimensions.h, originalWidth: elementDimensions.w}, afterFinishInternal: function (effect) { s.hideElement(effect.element); s.undoClipping(effect.element, elemClip); s.setStyle(effect.element, oldStyle); } }); } }, options); return new v.Scale(element, 5, options); }; // Compatibility with MochiKit 1.0 MochiKit.Visual.Color = MochiKit.Color.Color; MochiKit.Visual.getElementsComputedStyle = MochiKit.DOM.computedStyle; /* end of Rico adaptation */ MochiKit.Visual.__new__ = function () { var m = MochiKit.Base; m.nameFunctions(this); this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": m.concat(this.EXPORT, this.EXPORT_OK) }; }; MochiKit.Visual.EXPORT = [ "roundElement", "roundClass", "tagifyText", "multiple", "toggle", "Parallel", "Sequence", "Opacity", "Move", "Scale", "Highlight", "ScrollTo", "Morph", "fade", "appear", "puff", "blindUp", "blindDown", "switchOff", "dropOut", "shake", "slideDown", "slideUp", "squish", "grow", "shrink", "pulsate", "fold" ]; MochiKit.Visual.EXPORT_OK = [ "Base", "PAIRS" ]; MochiKit.Visual.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.Visual); MochiKit-1.4.2/lib/MochiKit/Format.js0000660000175000017500000002146711110670110016336 0ustar scottscott/*** MochiKit.Format 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('Format', ['Base']); MochiKit.Format.NAME = "MochiKit.Format"; MochiKit.Format.VERSION = "1.4.2"; MochiKit.Format.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.Format.toString = function () { return this.__repr__(); }; MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) { return function (num) { num = parseFloat(num); if (typeof(num) == "undefined" || num === null || isNaN(num)) { return placeholder; } var curheader = header; var curfooter = footer; if (num < 0) { num = -num; } else { curheader = curheader.replace(/-/, ""); } var me = arguments.callee; var fmt = MochiKit.Format.formatLocale(locale); if (isPercent) { num = num * 100.0; curfooter = fmt.percent + curfooter; } num = MochiKit.Format.roundToFixed(num, precision); var parts = num.split(/\./); var whole = parts[0]; var frac = (parts.length == 1) ? "" : parts[1]; var res = ""; while (whole.length < leadingZeros) { whole = "0" + whole; } if (separatorAt) { while (whole.length > separatorAt) { var i = whole.length - separatorAt; //res = res + fmt.separator + whole.substring(i, whole.length); res = fmt.separator + whole.substring(i, whole.length) + res; whole = whole.substring(0, i); } } res = whole + res; if (precision > 0) { while (frac.length < trailingZeros) { frac = frac + "0"; } res = res + fmt.decimal + frac; } return curheader + res + curfooter; }; }; /** @id MochiKit.Format.numberFormatter */ MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) { // http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html // | 0 | leading or trailing zeros // | # | just the number // | , | separator // | . | decimal separator // | % | Multiply by 100 and format as percent if (typeof(placeholder) == "undefined") { placeholder = ""; } var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/); if (!match) { throw TypeError("Invalid pattern"); } var header = pattern.substr(0, match.index); var footer = pattern.substr(match.index + match[0].length); if (header.search(/-/) == -1) { header = header + "-"; } var whole = match[1]; var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : ""; var isPercent = (typeof(match[3]) == "string" && match[3] != ""); var tmp = whole.split(/,/); var separatorAt; if (typeof(locale) == "undefined") { locale = "default"; } if (tmp.length == 1) { separatorAt = null; } else { separatorAt = tmp[1].length; } var leadingZeros = whole.length - whole.replace(/0/g, "").length; var trailingZeros = frac.length - frac.replace(/0/g, "").length; var precision = frac.length; var rval = MochiKit.Format._numberFormatter( placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros ); var m = MochiKit.Base; if (m) { var fn = arguments.callee; var args = m.concat(arguments); rval.repr = function () { return [ self.NAME, "(", map(m.repr, args).join(", "), ")" ].join(""); }; } return rval; }; /** @id MochiKit.Format.formatLocale */ MochiKit.Format.formatLocale = function (locale) { if (typeof(locale) == "undefined" || locale === null) { locale = "default"; } if (typeof(locale) == "string") { var rval = MochiKit.Format.LOCALE[locale]; if (typeof(rval) == "string") { rval = arguments.callee(rval); MochiKit.Format.LOCALE[locale] = rval; } return rval; } else { return locale; } }; /** @id MochiKit.Format.twoDigitAverage */ MochiKit.Format.twoDigitAverage = function (numerator, denominator) { if (denominator) { var res = numerator / denominator; if (!isNaN(res)) { return MochiKit.Format.twoDigitFloat(res); } } return "0"; }; /** @id MochiKit.Format.twoDigitFloat */ MochiKit.Format.twoDigitFloat = function (aNumber) { var res = roundToFixed(aNumber, 2); if (res.indexOf(".00") > 0) { return res.substring(0, res.length - 3); } else if (res.charAt(res.length - 1) == "0") { return res.substring(0, res.length - 1); } else { return res; } }; /** @id MochiKit.Format.lstrip */ MochiKit.Format.lstrip = function (str, /* optional */chars) { str = str + ""; if (typeof(str) != "string") { return null; } if (!chars) { return str.replace(/^\s+/, ""); } else { return str.replace(new RegExp("^[" + chars + "]+"), ""); } }; /** @id MochiKit.Format.rstrip */ MochiKit.Format.rstrip = function (str, /* optional */chars) { str = str + ""; if (typeof(str) != "string") { return null; } if (!chars) { return str.replace(/\s+$/, ""); } else { return str.replace(new RegExp("[" + chars + "]+$"), ""); } }; /** @id MochiKit.Format.strip */ MochiKit.Format.strip = function (str, /* optional */chars) { var self = MochiKit.Format; return self.rstrip(self.lstrip(str, chars), chars); }; /** @id MochiKit.Format.truncToFixed */ MochiKit.Format.truncToFixed = function (aNumber, precision) { var res = Math.floor(aNumber).toFixed(0); if (aNumber < 0) { res = Math.ceil(aNumber).toFixed(0); if (res.charAt(0) != "-" && precision > 0) { res = "-" + res; } } if (res.indexOf("e") < 0 && precision > 0) { var tail = aNumber.toString(); if (tail.indexOf("e") > 0) { tail = "."; } else if (tail.indexOf(".") < 0) { tail = "."; } else { tail = tail.substring(tail.indexOf(".")); } if (tail.length - 1 > precision) { tail = tail.substring(0, precision + 1); } while (tail.length - 1 < precision) { tail += "0"; } res += tail; } return res; }; /** @id MochiKit.Format.roundToFixed */ MochiKit.Format.roundToFixed = function (aNumber, precision) { var upper = Math.abs(aNumber) + 0.5 * Math.pow(10, -precision); var res = MochiKit.Format.truncToFixed(upper, precision); if (aNumber < 0) { res = "-" + res; } return res; }; /** @id MochiKit.Format.percentFormat */ MochiKit.Format.percentFormat = function (aNumber) { return MochiKit.Format.twoDigitFloat(100 * aNumber) + '%'; }; MochiKit.Format.EXPORT = [ "truncToFixed", "roundToFixed", "numberFormatter", "formatLocale", "twoDigitAverage", "twoDigitFloat", "percentFormat", "lstrip", "rstrip", "strip" ]; MochiKit.Format.LOCALE = { en_US: {separator: ",", decimal: ".", percent: "%"}, de_DE: {separator: ".", decimal: ",", percent: "%"}, pt_BR: {separator: ".", decimal: ",", percent: "%"}, fr_FR: {separator: " ", decimal: ",", percent: "%"}, "default": "en_US" }; MochiKit.Format.EXPORT_OK = []; MochiKit.Format.EXPORT_TAGS = { ':all': MochiKit.Format.EXPORT, ':common': MochiKit.Format.EXPORT }; MochiKit.Format.__new__ = function () { // MochiKit.Base.nameFunctions(this); var base = this.NAME + "."; var k, v, o; for (k in this.LOCALE) { o = this.LOCALE[k]; if (typeof(o) == "object") { o.repr = function () { return this.NAME; }; o.NAME = base + "LOCALE." + k; } } for (k in this) { o = this[k]; if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') { try { o.NAME = base + k; } catch (e) { // pass } } } }; MochiKit.Format.__new__(); if (typeof(MochiKit.Base) != "undefined") { MochiKit.Base._exportSymbols(this, MochiKit.Format); } else { (function (globals, module) { if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined') || (MochiKit.__export__ === false)) { var all = module.EXPORT_TAGS[":all"]; for (var i = 0; i < all.length; i++) { globals[all[i]] = module[all[i]]; } } })(this, MochiKit.Format); } MochiKit-1.4.2/lib/MochiKit/Test.js0000660000175000017500000001004311110666274016031 0ustar scottscott/*** MochiKit.Test 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('Test', ['Base']); MochiKit.Test.NAME = "MochiKit.Test"; MochiKit.Test.VERSION = "1.4.2"; MochiKit.Test.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.Test.toString = function () { return this.__repr__(); }; MochiKit.Test.EXPORT = ["runTests"]; MochiKit.Test.EXPORT_OK = []; MochiKit.Test.runTests = function (obj) { if (typeof(obj) == "string") { obj = JSAN.use(obj); } var suite = new MochiKit.Test.Suite(); suite.run(obj); }; MochiKit.Test.Suite = function () { this.testIndex = 0; MochiKit.Base.bindMethods(this); }; MochiKit.Test.Suite.prototype = { run: function (obj) { try { obj(this); } catch (e) { this.traceback(e); } }, traceback: function (e) { var items = MochiKit.Iter.sorted(MochiKit.Base.items(e)); print("not ok " + this.testIndex + " - Error thrown"); for (var i = 0; i < items.length; i++) { var kv = items[i]; if (kv[0] == "stack") { kv[1] = kv[1].split(/\n/)[0]; } this.print("# " + kv.join(": ")); } }, print: function (s) { print(s); }, is: function (got, expected, /* optional */message) { var res = 1; var msg = null; try { res = MochiKit.Base.compare(got, expected); } catch (e) { msg = "Can not compare " + typeof(got) + ":" + typeof(expected); } if (res) { msg = "Expected value did not compare equal"; } if (!res) { return this.testResult(true, message); } return this.testResult(false, message, [[msg], ["got:", got], ["expected:", expected]]); }, testResult: function (pass, msg, failures) { this.testIndex += 1; if (pass) { this.print("ok " + this.testIndex + " - " + msg); return; } this.print("not ok " + this.testIndex + " - " + msg); if (failures) { for (var i = 0; i < failures.length; i++) { this.print("# " + failures[i].join(" ")); } } }, isDeeply: function (got, expected, /* optional */message) { var m = MochiKit.Base; var res = 1; try { res = m.compare(got, expected); } catch (e) { // pass } if (res === 0) { return this.ok(true, message); } var gk = m.keys(got); var ek = m.keys(expected); gk.sort(); ek.sort(); if (m.compare(gk, ek)) { // differing keys var cmp = {}; var i; for (i = 0; i < gk.length; i++) { cmp[gk[i]] = "got"; } for (i = 0; i < ek.length; i++) { if (ek[i] in cmp) { delete cmp[ek[i]]; } else { cmp[ek[i]] = "expected"; } } var diffkeys = m.keys(cmp); diffkeys.sort(); var gotkeys = []; var expkeys = []; while (diffkeys.length) { var k = diffkeys.shift(); if (k in Object.prototype) { continue; } (cmp[k] == "got" ? gotkeys : expkeys).push(k); } } return this.testResult((!res), msg, (msg ? [["got:", got], ["expected:", expected]] : undefined) ); }, ok: function (res, message) { return this.testResult(res, message); } }; MochiKit.Test.__new__ = function () { var m = MochiKit.Base; this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); }; MochiKit.Test.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.Test); MochiKit-1.4.2/lib/MochiKit/MockDOM.js0000660000175000017500000000653211110666354016352 0ustar scottscott/*** MochiKit.MockDOM 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ if (typeof(MochiKit) == "undefined") { MochiKit = {}; } if (typeof(MochiKit.MockDOM) == "undefined") { MochiKit.MockDOM = {}; } MochiKit.MockDOM.NAME = "MochiKit.MockDOM"; MochiKit.MockDOM.VERSION = "1.4.2"; MochiKit.MockDOM.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; /** @id MochiKit.MockDOM.toString */ MochiKit.MockDOM.toString = function () { return this.__repr__(); }; /** @id MochiKit.MockDOM.createDocument */ MochiKit.MockDOM.createDocument = function () { var doc = new MochiKit.MockDOM.MockElement("DOCUMENT"); doc.body = doc.createElement("BODY"); doc.appendChild(doc.body); return doc; }; /** @id MochiKit.MockDOM.MockElement */ MochiKit.MockDOM.MockElement = function (name, data, ownerDocument) { this.tagName = this.nodeName = name.toUpperCase(); this.ownerDocument = ownerDocument || null; if (name == "DOCUMENT") { this.nodeType = 9; this.childNodes = []; } else if (typeof(data) == "string") { this.nodeValue = data; this.nodeType = 3; } else { this.nodeType = 1; this.childNodes = []; } if (name.substring(0, 1) == "<") { var nameattr = name.substring( name.indexOf('"') + 1, name.lastIndexOf('"')); name = name.substring(1, name.indexOf(" ")); this.tagName = this.nodeName = name.toUpperCase(); this.setAttribute("name", nameattr); } }; MochiKit.MockDOM.MockElement.prototype = { /** @id MochiKit.MockDOM.MockElement.prototype.createElement */ createElement: function (tagName) { return new MochiKit.MockDOM.MockElement(tagName, null, this.nodeType == 9 ? this : this.ownerDocument); }, /** @id MochiKit.MockDOM.MockElement.prototype.createTextNode */ createTextNode: function (text) { return new MochiKit.MockDOM.MockElement("text", text, this.nodeType == 9 ? this : this.ownerDocument); }, /** @id MochiKit.MockDOM.MockElement.prototype.setAttribute */ setAttribute: function (name, value) { this[name] = value; }, /** @id MochiKit.MockDOM.MockElement.prototype.getAttribute */ getAttribute: function (name) { return this[name]; }, /** @id MochiKit.MockDOM.MockElement.prototype.appendChild */ appendChild: function (child) { this.childNodes.push(child); }, /** @id MochiKit.MockDOM.MockElement.prototype.toString */ toString: function () { return "MockElement(" + this.tagName + ")"; }, /** @id MochiKit.MockDOM.MockElement.prototype.getElementsByTagName */ getElementsByTagName: function (tagName) { var foundElements = []; MochiKit.Base.nodeWalk(this, function(node){ if (tagName == '*' || tagName == node.tagName) { foundElements.push(node); return node.childNodes; } }); return foundElements; } }; /** @id MochiKit.MockDOM.EXPORT_OK */ MochiKit.MockDOM.EXPORT_OK = [ "mockElement", "createDocument" ]; /** @id MochiKit.MockDOM.EXPORT */ MochiKit.MockDOM.EXPORT = [ "document" ]; MochiKit.MockDOM.__new__ = function () { this.document = this.createDocument(); }; MochiKit.MockDOM.__new__(); MochiKit-1.4.2/lib/MochiKit/Style.js0000660000175000017500000005064711110666306016224 0ustar scottscott/*** MochiKit.Style 1.4.2 See for documentation, downloads, license, etc. (c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved. ***/ MochiKit.Base._deps('Style', ['Base', 'DOM']); MochiKit.Style.NAME = 'MochiKit.Style'; MochiKit.Style.VERSION = '1.4.2'; MochiKit.Style.__repr__ = function () { return '[' + this.NAME + ' ' + this.VERSION + ']'; }; MochiKit.Style.toString = function () { return this.__repr__(); }; MochiKit.Style.EXPORT_OK = []; MochiKit.Style.EXPORT = [ 'setStyle', 'setOpacity', 'getStyle', 'getElementDimensions', 'elementDimensions', // deprecated 'setElementDimensions', 'getElementPosition', 'elementPosition', // deprecated 'setElementPosition', "makePositioned", "undoPositioned", "makeClipping", "undoClipping", 'setDisplayForElement', 'hideElement', 'showElement', 'getViewportDimensions', 'getViewportPosition', 'Dimensions', 'Coordinates' ]; /* Dimensions */ /** @id MochiKit.Style.Dimensions */ MochiKit.Style.Dimensions = function (w, h) { this.w = w; this.h = h; }; MochiKit.Style.Dimensions.prototype.__repr__ = function () { var repr = MochiKit.Base.repr; return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}'; }; MochiKit.Style.Dimensions.prototype.toString = function () { return this.__repr__(); }; /* Coordinates */ /** @id MochiKit.Style.Coordinates */ MochiKit.Style.Coordinates = function (x, y) { this.x = x; this.y = y; }; MochiKit.Style.Coordinates.prototype.__repr__ = function () { var repr = MochiKit.Base.repr; return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}'; }; MochiKit.Style.Coordinates.prototype.toString = function () { return this.__repr__(); }; MochiKit.Base.update(MochiKit.Style, { /** @id MochiKit.Style.getStyle */ getStyle: function (elem, cssProperty) { var dom = MochiKit.DOM; var d = dom._document; elem = dom.getElement(elem); cssProperty = MochiKit.Base.camelize(cssProperty); if (!elem || elem == d) { return undefined; } if (cssProperty == 'opacity' && typeof(elem.filters) != 'undefined') { var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/); if (opacity && opacity[1]) { return parseFloat(opacity[1]) / 100; } return 1.0; } if (cssProperty == 'float' || cssProperty == 'cssFloat' || cssProperty == 'styleFloat') { if (elem.style["float"]) { return elem.style["float"]; } else if (elem.style.cssFloat) { return elem.style.cssFloat; } else if (elem.style.styleFloat) { return elem.style.styleFloat; } else { return "none"; } } var value = elem.style ? elem.style[cssProperty] : null; if (!value) { if (d.defaultView && d.defaultView.getComputedStyle) { var css = d.defaultView.getComputedStyle(elem, null); cssProperty = cssProperty.replace(/([A-Z])/g, '-$1' ).toLowerCase(); // from dojo.style.toSelectorCase value = css ? css.getPropertyValue(cssProperty) : null; } else if (elem.currentStyle) { value = elem.currentStyle[cssProperty]; if (/^\d/.test(value) && !/px$/.test(value) && cssProperty != 'fontWeight') { /* Convert to px using an hack from Dean Edwards */ var left = elem.style.left; var rsLeft = elem.runtimeStyle.left; elem.runtimeStyle.left = elem.currentStyle.left; elem.style.left = value || 0; value = elem.style.pixelLeft + "px"; elem.style.left = left; elem.runtimeStyle.left = rsLeft; } } } if (cssProperty == 'opacity') { value = parseFloat(value); } if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.findValue(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) { if (MochiKit.Style.getStyle(elem, 'position') == 'static') { value = 'auto'; } } return value == 'auto' ? null : value; }, /** @id MochiKit.Style.setStyle */ setStyle: function (elem, style) { elem = MochiKit.DOM.getElement(elem); for (var name in style) { switch (name) { case 'opacity': MochiKit.Style.setOpacity(elem, style[name]); break; case 'float': case 'cssFloat': case 'styleFloat': if (typeof(elem.style["float"]) != "undefined") { elem.style["float"] = style[name]; } else if (typeof(elem.style.cssFloat) != "undefined") { elem.style.cssFloat = style[name]; } else { elem.style.styleFloat = style[name]; } break; default: elem.style[MochiKit.Base.camelize(name)] = style[name]; } } }, /** @id MochiKit.Style.setOpacity */ setOpacity: function (elem, o) { elem = MochiKit.DOM.getElement(elem); var self = MochiKit.Style; if (o == 1) { var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)); elem.style["opacity"] = toSet ? 0.999999 : 1.0; if (/MSIE/.test(navigator.userAgent)) { elem.style['filter'] = self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, ''); } } else { if (o < 0.00001) { o = 0; } elem.style["opacity"] = o; if (/MSIE/.test(navigator.userAgent)) { elem.style['filter'] = self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')'; } } }, /* getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0. Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved. License: BSD, http://developer.yahoo.net/yui/license.txt */ /** @id MochiKit.Style.getElementPosition */ getElementPosition: function (elem, /* optional */relativeTo) { var self = MochiKit.Style; var dom = MochiKit.DOM; elem = dom.getElement(elem); if (!elem || (!(elem.x && elem.y) && (!elem.parentNode === null || self.getStyle(elem, 'display') == 'none'))) { return undefined; } var c = new self.Coordinates(0, 0); var box = null; var parent = null; var d = MochiKit.DOM._document; var de = d.documentElement; var b = d.body; if (!elem.parentNode && elem.x && elem.y) { /* it's just a MochiKit.Style.Coordinates object */ c.x += elem.x || 0; c.y += elem.y || 0; } else if (elem.getBoundingClientRect) { // IE shortcut /* The IE shortcut can be off by two. We fix it. See: http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp This is similar to the method used in MochiKit.Signal.Event.mouse(). */ box = elem.getBoundingClientRect(); c.x += box.left + (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0); c.y += box.top + (de.scrollTop || b.scrollTop) - (de.clientTop || 0); } else if (elem.offsetParent) { c.x += elem.offsetLeft; c.y += elem.offsetTop; parent = elem.offsetParent; if (parent != elem) { while (parent) { c.x += parseInt(parent.style.borderLeftWidth) || 0; c.y += parseInt(parent.style.borderTopWidth) || 0; c.x += parent.offsetLeft; c.y += parent.offsetTop; parent = parent.offsetParent; } } /* Opera < 9 and old Safari (absolute) incorrectly account for body offsetTop and offsetLeft. */ var ua = navigator.userAgent.toLowerCase(); if ((typeof(opera) != 'undefined' && parseFloat(opera.version()) < 9) || (ua.indexOf('AppleWebKit') != -1 && self.getStyle(elem, 'position') == 'absolute')) { c.x -= b.offsetLeft; c.y -= b.offsetTop; } // Adjust position for strange Opera scroll bug if (elem.parentNode) { parent = elem.parentNode; } else { parent = null; } while (parent) { var tagName = parent.tagName.toUpperCase(); if (tagName === 'BODY' || tagName === 'HTML') { break; } var disp = self.getStyle(parent, 'display'); // Handle strange Opera bug for some display if (disp.search(/^inline|table-row.*$/i)) { c.x -= parent.scrollLeft; c.y -= parent.scrollTop; } if (parent.parentNode) { parent = parent.parentNode; } else { parent = null; } } } if (typeof(relativeTo) != 'undefined') { relativeTo = arguments.callee(relativeTo); if (relativeTo) { c.x -= (relativeTo.x || 0); c.y -= (relativeTo.y || 0); } } return c; }, /** @id MochiKit.Style.setElementPosition */ setElementPosition: function (elem, newPos/* optional */, units) { elem = MochiKit.DOM.getElement(elem); if (typeof(units) == 'undefined') { units = 'px'; } var newStyle = {}; var isUndefNull = MochiKit.Base.isUndefinedOrNull; if (!isUndefNull(newPos.x)) { newStyle['left'] = newPos.x + units; } if (!isUndefNull(newPos.y)) { newStyle['top'] = newPos.y + units; } MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle}); }, /** @id MochiKit.Style.makePositioned */ makePositioned: function (element) { element = MochiKit.DOM.getElement(element); var pos = MochiKit.Style.getStyle(element, 'position'); if (pos == 'static' || !pos) { 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 (/Opera/.test(navigator.userAgent)) { element.style.top = 0; element.style.left = 0; } } }, /** @id MochiKit.Style.undoPositioned */ undoPositioned: function (element) { element = MochiKit.DOM.getElement(element); if (element.style.position == 'relative') { element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; } }, /** @id MochiKit.Style.makeClipping */ makeClipping: function (element) { element = MochiKit.DOM.getElement(element); var s = element.style; var oldOverflow = { 'overflow': s.overflow, 'overflow-x': s.overflowX, 'overflow-y': s.overflowY }; if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') { element.style.overflow = 'hidden'; element.style.overflowX = 'hidden'; element.style.overflowY = 'hidden'; } return oldOverflow; }, /** @id MochiKit.Style.undoClipping */ undoClipping: function (element, overflow) { element = MochiKit.DOM.getElement(element); if (typeof(overflow) == 'string') { element.style.overflow = overflow; } else if (overflow != null) { element.style.overflow = overflow['overflow']; element.style.overflowX = overflow['overflow-x']; element.style.overflowY = overflow['overflow-y']; } }, /** @id MochiKit.Style.getElementDimensions */ getElementDimensions: function (elem, contentSize/*optional*/) { var self = MochiKit.Style; var dom = MochiKit.DOM; if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') { return new self.Dimensions(elem.w || 0, elem.h || 0); } elem = dom.getElement(elem); if (!elem) { return undefined; } var disp = self.getStyle(elem, 'display'); // display can be empty/undefined on WebKit/KHTML if (disp == 'none' || disp == '' || typeof(disp) == 'undefined') { var s = elem.style; var originalVisibility = s.visibility; var originalPosition = s.position; var originalDisplay = s.display; s.visibility = 'hidden'; s.position = 'absolute'; s.display = self._getDefaultDisplay(elem); var originalWidth = elem.offsetWidth; var originalHeight = elem.offsetHeight; s.display = originalDisplay; s.position = originalPosition; s.visibility = originalVisibility; } else { originalWidth = elem.offsetWidth || 0; originalHeight = elem.offsetHeight || 0; } if (contentSize) { var tableCell = 'colSpan' in elem && 'rowSpan' in elem; var collapse = (tableCell && elem.parentNode && self.getStyle( elem.parentNode, 'borderCollapse') == 'collapse') if (collapse) { if (/MSIE/.test(navigator.userAgent)) { var borderLeftQuota = elem.previousSibling? 0.5 : 1; var borderRightQuota = elem.nextSibling? 0.5 : 1; } else { var borderLeftQuota = 0.5; var borderRightQuota = 0.5; } } else { var borderLeftQuota = 1; var borderRightQuota = 1; } originalWidth -= Math.round( (parseFloat(self.getStyle(elem, 'paddingLeft')) || 0) + (parseFloat(self.getStyle(elem, 'paddingRight')) || 0) + borderLeftQuota * (parseFloat(self.getStyle(elem, 'borderLeftWidth')) || 0) + borderRightQuota * (parseFloat(self.getStyle(elem, 'borderRightWidth')) || 0) ); if (tableCell) { if (/Gecko|Opera/.test(navigator.userAgent) && !/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)) { var borderHeightQuota = 0; } else if (/MSIE/.test(navigator.userAgent)) { var borderHeightQuota = 1; } else { var borderHeightQuota = collapse? 0.5 : 1; } } else { var borderHeightQuota = 1; } originalHeight -= Math.round( (parseFloat(self.getStyle(elem, 'paddingTop')) || 0) + (parseFloat(self.getStyle(elem, 'paddingBottom')) || 0) + borderHeightQuota * ( (parseFloat(self.getStyle(elem, 'borderTopWidth')) || 0) + (parseFloat(self.getStyle(elem, 'borderBottomWidth')) || 0)) ); } return new self.Dimensions(originalWidth, originalHeight); }, /** @id MochiKit.Style.setElementDimensions */ setElementDimensions: function (elem, newSize/* optional */, units) { elem = MochiKit.DOM.getElement(elem); if (typeof(units) == 'undefined') { units = 'px'; } var newStyle = {}; var isUndefNull = MochiKit.Base.isUndefinedOrNull; if (!isUndefNull(newSize.w)) { newStyle['width'] = newSize.w + units; } if (!isUndefNull(newSize.h)) { newStyle['height'] = newSize.h + units; } MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle}); }, _getDefaultDisplay: function (elem) { var self = MochiKit.Style; var dom = MochiKit.DOM; elem = dom.getElement(elem); if (!elem) { return undefined; } var tagName = elem.tagName.toUpperCase(); return self._defaultDisplay[tagName] || 'block'; }, /** @id MochiKit.Style.setDisplayForElement */ setDisplayForElement: function (display, element/*, ...*/) { var elements = MochiKit.Base.extend(null, arguments, 1); var getElement = MochiKit.DOM.getElement; for (var i = 0; i < elements.length; i++) { element = getElement(elements[i]); if (element) { element.style.display = display; } } }, /** @id MochiKit.Style.getViewportDimensions */ getViewportDimensions: function () { var d = new MochiKit.Style.Dimensions(); var w = MochiKit.DOM._window; var b = MochiKit.DOM._document.body; if (w.innerWidth) { d.w = w.innerWidth; d.h = w.innerHeight; } else if (b && b.parentElement && b.parentElement.clientWidth) { d.w = b.parentElement.clientWidth; d.h = b.parentElement.clientHeight; } else if (b && b.clientWidth) { d.w = b.clientWidth; d.h = b.clientHeight; } return d; }, /** @id MochiKit.Style.getViewportPosition */ getViewportPosition: function () { var c = new MochiKit.Style.Coordinates(0, 0); var d = MochiKit.DOM._document; var de = d.documentElement; var db = d.body; if (de && (de.scrollTop || de.scrollLeft)) { c.x = de.scrollLeft; c.y = de.scrollTop; } else if (db) { c.x = db.scrollLeft; c.y = db.scrollTop; } return c; }, __new__: function () { var m = MochiKit.Base; var inlines = ['A','ABBR','ACRONYM','B','BASEFONT','BDO','BIG','BR', 'CITE','CODE','DFN','EM','FONT','I','IMG','KBD','LABEL', 'Q','S','SAMP','SMALL','SPAN','STRIKE','STRONG','SUB', 'SUP','TEXTAREA','TT','U','VAR']; this._defaultDisplay = { 'TABLE': 'table', 'THEAD': 'table-header-group', 'TBODY': 'table-row-group', 'TFOOT': 'table-footer-group', 'COLGROUP': 'table-column-group', 'COL': 'table-column', 'TR': 'table-row', 'TD': 'table-cell', 'TH': 'table-cell', 'CAPTION': 'table-caption', 'LI': 'list-item', 'INPUT': 'inline-block', 'SELECT': 'inline-block' }; // CSS 'display' support in IE6/7 is just broken... if (/MSIE/.test(navigator.userAgent)) { for (var k in this._defaultDisplay) { var v = this._defaultDisplay[k]; if (v.indexOf('table') == 0) { this._defaultDisplay[k] = 'block'; } } } for (var i = 0; i < inlines.length; i++) { this._defaultDisplay[inlines[i]] = 'inline'; } this.elementPosition = this.getElementPosition; this.elementDimensions = this.getElementDimensions; this.hideElement = m.partial(this.setDisplayForElement, 'none'); // TODO: showElement could be improved by using getDefaultDisplay. this.showElement = m.partial(this.setDisplayForElement, 'block'); this.EXPORT_TAGS = { ':common': this.EXPORT, ':all': m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); } }); MochiKit.Style.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.Style); MochiKit-1.4.2/lib/MochiKit/Sortable.js0000660000175000017500000004724611110666316016701 0ustar scottscott/*** Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) Mochi-ized By Thomas Herve (_firstname_@nimail.org) See scriptaculous.js for full license. ***/ MochiKit.Base._deps('Sortable', ['Base', 'Iter', 'DOM', 'Position', 'DragAndDrop']); MochiKit.Sortable.NAME = 'MochiKit.Sortable'; MochiKit.Sortable.VERSION = '1.4.2'; MochiKit.Sortable.__repr__ = function () { return '[' + this.NAME + ' ' + this.VERSION + ']'; }; MochiKit.Sortable.toString = function () { return this.__repr__(); }; MochiKit.Sortable.EXPORT = [ ]; MochiKit.Sortable.EXPORT_OK = [ ]; MochiKit.Base.update(MochiKit.Sortable, { /*** Manage sortables. Mainly use the create function to add a sortable. ***/ sortables: {}, _findRootElement: function (element) { while (element.tagName.toUpperCase() != "BODY") { if (element.id && MochiKit.Sortable.sortables[element.id]) { return element; } element = element.parentNode; } }, _createElementId: function(element) { if (element.id == null || element.id == "") { var d = MochiKit.DOM; var id; var count = 1; while (d.getElement(id = "sortable" + count) != null) { count += 1; } d.setNodeAttribute(element, "id", id); } }, /** @id MochiKit.Sortable.options */ options: function (element) { element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element)); if (!element) { return; } return MochiKit.Sortable.sortables[element.id]; }, /** @id MochiKit.Sortable.destroy */ destroy: function (element){ var s = MochiKit.Sortable.options(element); var b = MochiKit.Base; var d = MochiKit.DragAndDrop; if (s) { MochiKit.Signal.disconnect(s.startHandle); MochiKit.Signal.disconnect(s.endHandle); b.map(function (dr) { d.Droppables.remove(dr); }, s.droppables); b.map(function (dr) { dr.destroy(); }, s.draggables); delete MochiKit.Sortable.sortables[s.element.id]; } }, /** @id MochiKit.Sortable.create */ create: function (element, options) { element = MochiKit.DOM.getElement(element); var self = MochiKit.Sortable; self._createElementId(element); /** @id MochiKit.Sortable.options */ options = MochiKit.Base.update({ /** @id MochiKit.Sortable.element */ element: element, /** @id MochiKit.Sortable.tag */ tag: 'li', // assumes li children, override with tag: 'tagname' /** @id MochiKit.Sortable.dropOnEmpty */ dropOnEmpty: false, /** @id MochiKit.Sortable.tree */ tree: false, /** @id MochiKit.Sortable.treeTag */ treeTag: 'ul', /** @id MochiKit.Sortable.overlap */ overlap: 'vertical', // one of 'vertical', 'horizontal' /** @id MochiKit.Sortable.constraint */ constraint: 'vertical', // one of 'vertical', 'horizontal', false // also takes array of elements (or ids); or false /** @id MochiKit.Sortable.containment */ containment: [element], /** @id MochiKit.Sortable.handle */ handle: false, // or a CSS class /** @id MochiKit.Sortable.only */ only: false, /** @id MochiKit.Sortable.hoverclass */ hoverclass: null, /** @id MochiKit.Sortable.ghosting */ ghosting: false, /** @id MochiKit.Sortable.scroll */ scroll: false, /** @id MochiKit.Sortable.scrollSensitivity */ scrollSensitivity: 20, /** @id MochiKit.Sortable.scrollSpeed */ scrollSpeed: 15, /** @id MochiKit.Sortable.format */ format: /^[^_]*_(.*)$/, /** @id MochiKit.Sortable.onChange */ onChange: MochiKit.Base.noop, /** @id MochiKit.Sortable.onUpdate */ onUpdate: MochiKit.Base.noop, /** @id MochiKit.Sortable.accept */ accept: null }, options); // clear any old sortable with same element self.destroy(element); // build options for the draggables var options_for_draggable = { revert: true, ghosting: options.ghosting, scroll: options.scroll, scrollSensitivity: options.scrollSensitivity, scrollSpeed: options.scrollSpeed, constraint: options.constraint, handle: options.handle }; if (options.starteffect) { options_for_draggable.starteffect = options.starteffect; } if (options.reverteffect) { options_for_draggable.reverteffect = options.reverteffect; } else if (options.ghosting) { options_for_draggable.reverteffect = function (innerelement) { innerelement.style.top = 0; innerelement.style.left = 0; }; } if (options.endeffect) { options_for_draggable.endeffect = options.endeffect; } if (options.zindex) { options_for_draggable.zindex = options.zindex; } // build options for the droppables var options_for_droppable = { overlap: options.overlap, containment: options.containment, hoverclass: options.hoverclass, onhover: self.onHover, tree: options.tree, accept: options.accept } var options_for_tree = { onhover: self.onEmptyHover, overlap: options.overlap, containment: options.containment, hoverclass: options.hoverclass, accept: options.accept } // fix for gecko engine MochiKit.DOM.removeEmptyTextNodes(element); options.draggables = []; options.droppables = []; // drop on empty handling if (options.dropOnEmpty || options.tree) { new MochiKit.DragAndDrop.Droppable(element, options_for_tree); options.droppables.push(element); } MochiKit.Base.map(function (e) { // handles are per-draggable var handle = options.handle ? MochiKit.DOM.getFirstElementByTagAndClassName(null, options.handle, e) : e; options.draggables.push( new MochiKit.DragAndDrop.Draggable(e, MochiKit.Base.update(options_for_draggable, {handle: handle}))); new MochiKit.DragAndDrop.Droppable(e, options_for_droppable); if (options.tree) { e.treeNode = element; } options.droppables.push(e); }, (self.findElements(element, options) || [])); if (options.tree) { MochiKit.Base.map(function (e) { new MochiKit.DragAndDrop.Droppable(e, options_for_tree); e.treeNode = element; options.droppables.push(e); }, (self.findTreeElements(element, options) || [])); } // keep reference self.sortables[element.id] = options; options.lastValue = self.serialize(element); options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start', MochiKit.Base.partial(self.onStart, element)); options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end', MochiKit.Base.partial(self.onEnd, element)); }, /** @id MochiKit.Sortable.onStart */ onStart: function (element, draggable) { var self = MochiKit.Sortable; var options = self.options(element); options.lastValue = self.serialize(options.element); }, /** @id MochiKit.Sortable.onEnd */ onEnd: function (element, draggable) { var self = MochiKit.Sortable; self.unmark(); var options = self.options(element); if (options.lastValue != self.serialize(options.element)) { options.onUpdate(options.element); } }, // return all suitable-for-sortable elements in a guaranteed order /** @id MochiKit.Sortable.findElements */ findElements: function (element, options) { return MochiKit.Sortable.findChildren(element, options.only, options.tree, options.tag); }, /** @id MochiKit.Sortable.findTreeElements */ findTreeElements: function (element, options) { return MochiKit.Sortable.findChildren( element, options.only, options.tree ? true : false, options.treeTag); }, /** @id MochiKit.Sortable.findChildren */ findChildren: function (element, only, recursive, tagName) { if (!element.hasChildNodes()) { return null; } tagName = tagName.toUpperCase(); if (only) { only = MochiKit.Base.flattenArray([only]); } var elements = []; MochiKit.Base.map(function (e) { if (e.tagName && e.tagName.toUpperCase() == tagName && (!only || MochiKit.Iter.some(only, function (c) { return MochiKit.DOM.hasElementClass(e, c); }))) { elements.push(e); } if (recursive) { var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName); if (grandchildren && grandchildren.length > 0) { elements = elements.concat(grandchildren); } } }, element.childNodes); return elements; }, /** @id MochiKit.Sortable.onHover */ onHover: function (element, dropon, overlap) { if (MochiKit.DOM.isChildNode(dropon, element)) { return; } var self = MochiKit.Sortable; if (overlap > .33 && overlap < .66 && self.options(dropon).tree) { return; } else if (overlap > 0.5) { self.mark(dropon, 'before'); if (dropon.previousSibling != element) { var oldParentNode = element.parentNode; element.style.visibility = 'hidden'; // fix gecko rendering dropon.parentNode.insertBefore(element, dropon); if (dropon.parentNode != oldParentNode) { self.options(oldParentNode).onChange(element); } self.options(dropon.parentNode).onChange(element); } } else { self.mark(dropon, 'after'); var nextElement = dropon.nextSibling || null; if (nextElement != element) { var oldParentNode = element.parentNode; element.style.visibility = 'hidden'; // fix gecko rendering dropon.parentNode.insertBefore(element, nextElement); if (dropon.parentNode != oldParentNode) { self.options(oldParentNode).onChange(element); } self.options(dropon.parentNode).onChange(element); } } }, _offsetSize: function (element, type) { if (type == 'vertical' || type == 'height') { return element.offsetHeight; } else { return element.offsetWidth; } }, /** @id MochiKit.Sortable.onEmptyHover */ onEmptyHover: function (element, dropon, overlap) { var oldParentNode = element.parentNode; var self = MochiKit.Sortable; var droponOptions = self.options(dropon); if (!MochiKit.DOM.isChildNode(dropon, element)) { var index; var children = self.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only}); var child = null; if (children) { var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); for (index = 0; index < children.length; index += 1) { if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) { offset -= self._offsetSize(children[index], droponOptions.overlap); } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) { child = index + 1 < children.length ? children[index + 1] : null; break; } else { child = children[index]; break; } } } dropon.insertBefore(element, child); self.options(oldParentNode).onChange(element); droponOptions.onChange(element); } }, /** @id MochiKit.Sortable.unmark */ unmark: function () { var m = MochiKit.Sortable._marker; if (m) { MochiKit.Style.hideElement(m); } }, /** @id MochiKit.Sortable.mark */ mark: function (dropon, position) { // mark on ghosting only var d = MochiKit.DOM; var self = MochiKit.Sortable; var sortable = self.options(dropon.parentNode); if (sortable && !sortable.ghosting) { return; } if (!self._marker) { self._marker = d.getElement('dropmarker') || document.createElement('DIV'); MochiKit.Style.hideElement(self._marker); d.addElementClass(self._marker, 'dropmarker'); self._marker.style.position = 'absolute'; document.getElementsByTagName('body').item(0).appendChild(self._marker); } var offsets = MochiKit.Position.cumulativeOffset(dropon); self._marker.style.left = offsets.x + 'px'; self._marker.style.top = offsets.y + 'px'; if (position == 'after') { if (sortable.overlap == 'horizontal') { self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px'; } else { self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px'; } } MochiKit.Style.showElement(self._marker); }, _tree: function (element, options, parent) { var self = MochiKit.Sortable; var children = self.findElements(element, options) || []; for (var i = 0; i < children.length; ++i) { var match = children[i].id.match(options.format); if (!match) { continue; } var child = { id: encodeURIComponent(match ? match[1] : null), element: element, parent: parent, children: [], position: parent.children.length, container: self._findChildrenElement(children[i], options.treeTag.toUpperCase()) } /* Get the element containing the children and recurse over it */ if (child.container) { self._tree(child.container, options, child) } parent.children.push (child); } return parent; }, /* Finds the first element of the given tag type within a parent element. Used for finding the first LI[ST] within a L[IST]I[TEM].*/ _findChildrenElement: function (element, containerTag) { if (element && element.hasChildNodes) { containerTag = containerTag.toUpperCase(); for (var i = 0; i < element.childNodes.length; ++i) { if (element.childNodes[i].tagName.toUpperCase() == containerTag) { return element.childNodes[i]; } } } return null; }, /** @id MochiKit.Sortable.tree */ tree: function (element, options) { element = MochiKit.DOM.getElement(element); var sortableOptions = MochiKit.Sortable.options(element); options = MochiKit.Base.update({ tag: sortableOptions.tag, treeTag: sortableOptions.treeTag, only: sortableOptions.only, name: element.id, format: sortableOptions.format }, options || {}); var root = { id: null, parent: null, children: new Array, container: element, position: 0 } return MochiKit.Sortable._tree(element, options, root); }, /** * Specifies the sequence for the Sortable. * @param {Node} element Element to use as the Sortable. * @param {Object} newSequence New sequence to use. * @param {Object} options Options to use fro the Sortable. */ setSequence: function (element, newSequence, options) { var self = MochiKit.Sortable; var b = MochiKit.Base; element = MochiKit.DOM.getElement(element); options = b.update(self.options(element), options || {}); var nodeMap = {}; b.map(function (n) { var m = n.id.match(options.format); if (m) { nodeMap[m[1]] = [n, n.parentNode]; } n.parentNode.removeChild(n); }, self.findElements(element, options)); b.map(function (ident) { var n = nodeMap[ident]; if (n) { n[1].appendChild(n[0]); delete nodeMap[ident]; } }, newSequence); }, /* Construct a [i] index for a particular node */ _constructIndex: function (node) { var index = ''; do { if (node.id) { index = '[' + node.position + ']' + index; } } while ((node = node.parent) != null); return index; }, /** @id MochiKit.Sortable.sequence */ sequence: function (element, options) { element = MochiKit.DOM.getElement(element); var self = MochiKit.Sortable; var options = MochiKit.Base.update(self.options(element), options || {}); return MochiKit.Base.map(function (item) { return item.id.match(options.format) ? item.id.match(options.format)[1] : ''; }, MochiKit.DOM.getElement(self.findElements(element, options) || [])); }, /** * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest. * These options override the Sortable options for the serialization only. * @param {Node} element Element to serialize. * @param {Object} options Serialization options. */ serialize: function (element, options) { element = MochiKit.DOM.getElement(element); var self = MochiKit.Sortable; options = MochiKit.Base.update(self.options(element), options || {}); var name = encodeURIComponent(options.name || element.id); if (options.tree) { return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) { return [name + self._constructIndex(item) + "[id]=" + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); }, self.tree(element, options).children)).join('&'); } else { return MochiKit.Base.map(function (item) { return name + "[]=" + encodeURIComponent(item); }, self.sequence(element, options)).join('&'); } } }); // trunk compatibility MochiKit.Sortable.Sortable = MochiKit.Sortable; MochiKit.Sortable.__new__ = function () { MochiKit.Base.nameFunctions(this); this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) }; }; MochiKit.Sortable.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.Sortable); MochiKit-1.4.2/lib/MochiKit/Iter.js0000660000175000017500000005671311110670102016014 0ustar scottscott/*** MochiKit.Iter 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('Iter', ['Base']); MochiKit.Iter.NAME = "MochiKit.Iter"; MochiKit.Iter.VERSION = "1.4.2"; MochiKit.Base.update(MochiKit.Iter, { __repr__: function () { return "[" + this.NAME + " " + this.VERSION + "]"; }, toString: function () { return this.__repr__(); }, /** @id MochiKit.Iter.registerIteratorFactory */ registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) { MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override); }, /** @id MochiKit.Iter.isIterable */ isIterable: function(o) { return o != null && (typeof(o.next) == "function" || typeof(o.iter) == "function"); }, /** @id MochiKit.Iter.iter */ iter: function (iterable, /* optional */ sentinel) { var self = MochiKit.Iter; if (arguments.length == 2) { return self.takewhile( function (a) { return a != sentinel; }, iterable ); } if (typeof(iterable.next) == 'function') { return iterable; } else if (typeof(iterable.iter) == 'function') { return iterable.iter(); /* } else if (typeof(iterable.__iterator__) == 'function') { // // XXX: We can't support JavaScript 1.7 __iterator__ directly // because of Object.prototype.__iterator__ // return iterable.__iterator__(); */ } try { return self.iteratorRegistry.match(iterable); } catch (e) { var m = MochiKit.Base; if (e == m.NotFound) { e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable"); } throw e; } }, /** @id MochiKit.Iter.count */ count: function (n) { if (!n) { n = 0; } var m = MochiKit.Base; return { repr: function () { return "count(" + n + ")"; }, toString: m.forwardCall("repr"), next: m.counter(n) }; }, /** @id MochiKit.Iter.cycle */ cycle: function (p) { var self = MochiKit.Iter; var m = MochiKit.Base; var lst = []; var iterator = self.iter(p); return { repr: function () { return "cycle(...)"; }, toString: m.forwardCall("repr"), next: function () { try { var rval = iterator.next(); lst.push(rval); return rval; } catch (e) { if (e != self.StopIteration) { throw e; } if (lst.length === 0) { this.next = function () { throw self.StopIteration; }; } else { var i = -1; this.next = function () { i = (i + 1) % lst.length; return lst[i]; }; } return this.next(); } } }; }, /** @id MochiKit.Iter.repeat */ repeat: function (elem, /* optional */n) { var m = MochiKit.Base; if (typeof(n) == 'undefined') { return { repr: function () { return "repeat(" + m.repr(elem) + ")"; }, toString: m.forwardCall("repr"), next: function () { return elem; } }; } return { repr: function () { return "repeat(" + m.repr(elem) + ", " + n + ")"; }, toString: m.forwardCall("repr"), next: function () { if (n <= 0) { throw MochiKit.Iter.StopIteration; } n -= 1; return elem; } }; }, /** @id MochiKit.Iter.next */ next: function (iterator) { return iterator.next(); }, /** @id MochiKit.Iter.izip */ izip: function (p, q/*, ...*/) { var m = MochiKit.Base; var self = MochiKit.Iter; var next = self.next; var iterables = m.map(self.iter, arguments); return { repr: function () { return "izip(...)"; }, toString: m.forwardCall("repr"), next: function () { return m.map(next, iterables); } }; }, /** @id MochiKit.Iter.ifilter */ ifilter: function (pred, seq) { var m = MochiKit.Base; seq = MochiKit.Iter.iter(seq); if (pred === null) { pred = m.operator.truth; } return { repr: function () { return "ifilter(...)"; }, toString: m.forwardCall("repr"), next: function () { while (true) { var rval = seq.next(); if (pred(rval)) { return rval; } } // mozilla warnings aren't too bright return undefined; } }; }, /** @id MochiKit.Iter.ifilterfalse */ ifilterfalse: function (pred, seq) { var m = MochiKit.Base; seq = MochiKit.Iter.iter(seq); if (pred === null) { pred = m.operator.truth; } return { repr: function () { return "ifilterfalse(...)"; }, toString: m.forwardCall("repr"), next: function () { while (true) { var rval = seq.next(); if (!pred(rval)) { return rval; } } // mozilla warnings aren't too bright return undefined; } }; }, /** @id MochiKit.Iter.islice */ islice: function (seq/*, [start,] stop[, step] */) { var self = MochiKit.Iter; var m = MochiKit.Base; seq = self.iter(seq); var start = 0; var stop = 0; var step = 1; var i = -1; if (arguments.length == 2) { stop = arguments[1]; } else if (arguments.length == 3) { start = arguments[1]; stop = arguments[2]; } else { start = arguments[1]; stop = arguments[2]; step = arguments[3]; } return { repr: function () { return "islice(" + ["...", start, stop, step].join(", ") + ")"; }, toString: m.forwardCall("repr"), next: function () { var rval; while (i < start) { rval = seq.next(); i++; } if (start >= stop) { throw self.StopIteration; } start += step; return rval; } }; }, /** @id MochiKit.Iter.imap */ imap: function (fun, p, q/*, ...*/) { var m = MochiKit.Base; var self = MochiKit.Iter; var iterables = m.map(self.iter, m.extend(null, arguments, 1)); var map = m.map; var next = self.next; return { repr: function () { return "imap(...)"; }, toString: m.forwardCall("repr"), next: function () { return fun.apply(this, map(next, iterables)); } }; }, /** @id MochiKit.Iter.applymap */ applymap: function (fun, seq, self) { seq = MochiKit.Iter.iter(seq); var m = MochiKit.Base; return { repr: function () { return "applymap(...)"; }, toString: m.forwardCall("repr"), next: function () { return fun.apply(self, seq.next()); } }; }, /** @id MochiKit.Iter.chain */ chain: function (p, q/*, ...*/) { // dumb fast path var self = MochiKit.Iter; var m = MochiKit.Base; if (arguments.length == 1) { return self.iter(arguments[0]); } var argiter = m.map(self.iter, arguments); return { repr: function () { return "chain(...)"; }, toString: m.forwardCall("repr"), next: function () { while (argiter.length > 1) { try { var result = argiter[0].next(); return result; } catch (e) { if (e != self.StopIteration) { throw e; } argiter.shift(); var result = argiter[0].next(); return result; } } if (argiter.length == 1) { // optimize last element var arg = argiter.shift(); this.next = m.bind("next", arg); return this.next(); } throw self.StopIteration; } }; }, /** @id MochiKit.Iter.takewhile */ takewhile: function (pred, seq) { var self = MochiKit.Iter; seq = self.iter(seq); return { repr: function () { return "takewhile(...)"; }, toString: MochiKit.Base.forwardCall("repr"), next: function () { var rval = seq.next(); if (!pred(rval)) { this.next = function () { throw self.StopIteration; }; this.next(); } return rval; } }; }, /** @id MochiKit.Iter.dropwhile */ dropwhile: function (pred, seq) { seq = MochiKit.Iter.iter(seq); var m = MochiKit.Base; var bind = m.bind; return { "repr": function () { return "dropwhile(...)"; }, "toString": m.forwardCall("repr"), "next": function () { while (true) { var rval = seq.next(); if (!pred(rval)) { break; } } this.next = bind("next", seq); return rval; } }; }, _tee: function (ident, sync, iterable) { sync.pos[ident] = -1; var m = MochiKit.Base; var listMin = m.listMin; return { repr: function () { return "tee(" + ident + ", ...)"; }, toString: m.forwardCall("repr"), next: function () { var rval; var i = sync.pos[ident]; if (i == sync.max) { rval = iterable.next(); sync.deque.push(rval); sync.max += 1; sync.pos[ident] += 1; } else { rval = sync.deque[i - sync.min]; sync.pos[ident] += 1; if (i == sync.min && listMin(sync.pos) != sync.min) { sync.min += 1; sync.deque.shift(); } } return rval; } }; }, /** @id MochiKit.Iter.tee */ tee: function (iterable, n/* = 2 */) { var rval = []; var sync = { "pos": [], "deque": [], "max": -1, "min": -1 }; if (arguments.length == 1 || typeof(n) == "undefined" || n === null) { n = 2; } var self = MochiKit.Iter; iterable = self.iter(iterable); var _tee = self._tee; for (var i = 0; i < n; i++) { rval.push(_tee(i, sync, iterable)); } return rval; }, /** @id MochiKit.Iter.list */ list: function (iterable) { // Fast-path for Array and Array-like var rval; if (iterable instanceof Array) { return iterable.slice(); } // this is necessary to avoid a Safari crash if (typeof(iterable) == "function" && !(iterable instanceof Function) && typeof(iterable.length) == 'number') { rval = []; for (var i = 0; i < iterable.length; i++) { rval.push(iterable[i]); } return rval; } var self = MochiKit.Iter; iterable = self.iter(iterable); var rval = []; var a_val; try { while (true) { a_val = iterable.next(); rval.push(a_val); } } catch (e) { if (e != self.StopIteration) { throw e; } return rval; } // mozilla warnings aren't too bright return undefined; }, /** @id MochiKit.Iter.reduce */ reduce: function (fn, iterable, /* optional */initial) { var i = 0; var x = initial; var self = MochiKit.Iter; iterable = self.iter(iterable); if (arguments.length < 3) { try { x = iterable.next(); } catch (e) { if (e == self.StopIteration) { e = new TypeError("reduce() of empty sequence with no initial value"); } throw e; } i++; } try { while (true) { x = fn(x, iterable.next()); } } catch (e) { if (e != self.StopIteration) { throw e; } } return x; }, /** @id MochiKit.Iter.range */ range: function (/* [start,] stop[, step] */) { var start = 0; var stop = 0; var step = 1; if (arguments.length == 1) { stop = arguments[0]; } else if (arguments.length == 2) { start = arguments[0]; stop = arguments[1]; } else if (arguments.length == 3) { start = arguments[0]; stop = arguments[1]; step = arguments[2]; } else { throw new TypeError("range() takes 1, 2, or 3 arguments!"); } if (step === 0) { throw new TypeError("range() step must not be 0"); } return { next: function () { if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) { throw MochiKit.Iter.StopIteration; } var rval = start; start += step; return rval; }, repr: function () { return "range(" + [start, stop, step].join(", ") + ")"; }, toString: MochiKit.Base.forwardCall("repr") }; }, /** @id MochiKit.Iter.sum */ sum: function (iterable, start/* = 0 */) { if (typeof(start) == "undefined" || start === null) { start = 0; } var x = start; var self = MochiKit.Iter; iterable = self.iter(iterable); try { while (true) { x += iterable.next(); } } catch (e) { if (e != self.StopIteration) { throw e; } } return x; }, /** @id MochiKit.Iter.exhaust */ exhaust: function (iterable) { var self = MochiKit.Iter; iterable = self.iter(iterable); try { while (true) { iterable.next(); } } catch (e) { if (e != self.StopIteration) { throw e; } } }, /** @id MochiKit.Iter.forEach */ forEach: function (iterable, func, /* optional */obj) { var m = MochiKit.Base; var self = MochiKit.Iter; if (arguments.length > 2) { func = m.bind(func, obj); } // fast path for array if (m.isArrayLike(iterable) && !self.isIterable(iterable)) { try { for (var i = 0; i < iterable.length; i++) { func(iterable[i]); } } catch (e) { if (e != self.StopIteration) { throw e; } } } else { self.exhaust(self.imap(func, iterable)); } }, /** @id MochiKit.Iter.every */ every: function (iterable, func) { var self = MochiKit.Iter; try { self.ifilterfalse(func, iterable).next(); return false; } catch (e) { if (e != self.StopIteration) { throw e; } return true; } }, /** @id MochiKit.Iter.sorted */ sorted: function (iterable, /* optional */cmp) { var rval = MochiKit.Iter.list(iterable); if (arguments.length == 1) { cmp = MochiKit.Base.compare; } rval.sort(cmp); return rval; }, /** @id MochiKit.Iter.reversed */ reversed: function (iterable) { var rval = MochiKit.Iter.list(iterable); rval.reverse(); return rval; }, /** @id MochiKit.Iter.some */ some: function (iterable, func) { var self = MochiKit.Iter; try { self.ifilter(func, iterable).next(); return true; } catch (e) { if (e != self.StopIteration) { throw e; } return false; } }, /** @id MochiKit.Iter.iextend */ iextend: function (lst, iterable) { var m = MochiKit.Base; var self = MochiKit.Iter; if (m.isArrayLike(iterable) && !self.isIterable(iterable)) { // fast-path for array-like for (var i = 0; i < iterable.length; i++) { lst.push(iterable[i]); } } else { iterable = self.iter(iterable); try { while (true) { lst.push(iterable.next()); } } catch (e) { if (e != self.StopIteration) { throw e; } } } return lst; }, /** @id MochiKit.Iter.groupby */ groupby: function(iterable, /* optional */ keyfunc) { var m = MochiKit.Base; var self = MochiKit.Iter; if (arguments.length < 2) { keyfunc = m.operator.identity; } iterable = self.iter(iterable); // shared var pk = undefined; var k = undefined; var v; function fetch() { v = iterable.next(); k = keyfunc(v); }; function eat() { var ret = v; v = undefined; return ret; }; var first = true; var compare = m.compare; return { repr: function () { return "groupby(...)"; }, next: function() { // iterator-next // iterate until meet next group while (compare(k, pk) === 0) { fetch(); if (first) { first = false; break; } } pk = k; return [k, { next: function() { // subiterator-next if (v == undefined) { // Is there something to eat? fetch(); } if (compare(k, pk) !== 0) { throw self.StopIteration; } return eat(); } }]; } }; }, /** @id MochiKit.Iter.groupby_as_array */ groupby_as_array: function (iterable, /* optional */ keyfunc) { var m = MochiKit.Base; var self = MochiKit.Iter; if (arguments.length < 2) { keyfunc = m.operator.identity; } iterable = self.iter(iterable); var result = []; var first = true; var prev_key; var compare = m.compare; while (true) { try { var value = iterable.next(); var key = keyfunc(value); } catch (e) { if (e == self.StopIteration) { break; } throw e; } if (first || compare(key, prev_key) !== 0) { var values = []; result.push([key, values]); } values.push(value); first = false; prev_key = key; } return result; }, /** @id MochiKit.Iter.arrayLikeIter */ arrayLikeIter: function (iterable) { var i = 0; return { repr: function () { return "arrayLikeIter(...)"; }, toString: MochiKit.Base.forwardCall("repr"), next: function () { if (i >= iterable.length) { throw MochiKit.Iter.StopIteration; } return iterable[i++]; } }; }, /** @id MochiKit.Iter.hasIterateNext */ hasIterateNext: function (iterable) { return (iterable && typeof(iterable.iterateNext) == "function"); }, /** @id MochiKit.Iter.iterateNextIter */ iterateNextIter: function (iterable) { return { repr: function () { return "iterateNextIter(...)"; }, toString: MochiKit.Base.forwardCall("repr"), next: function () { var rval = iterable.iterateNext(); if (rval === null || rval === undefined) { throw MochiKit.Iter.StopIteration; } return rval; } }; } }); MochiKit.Iter.EXPORT_OK = [ "iteratorRegistry", "arrayLikeIter", "hasIterateNext", "iterateNextIter" ]; MochiKit.Iter.EXPORT = [ "StopIteration", "registerIteratorFactory", "iter", "count", "cycle", "repeat", "next", "izip", "ifilter", "ifilterfalse", "islice", "imap", "applymap", "chain", "takewhile", "dropwhile", "tee", "list", "reduce", "range", "sum", "exhaust", "forEach", "every", "sorted", "reversed", "some", "iextend", "groupby", "groupby_as_array" ]; MochiKit.Iter.__new__ = function () { var m = MochiKit.Base; // Re-use StopIteration if exists (e.g. SpiderMonkey) if (typeof(StopIteration) != "undefined") { this.StopIteration = StopIteration; } else { /** @id MochiKit.Iter.StopIteration */ this.StopIteration = new m.NamedError("StopIteration"); } this.iteratorRegistry = new m.AdapterRegistry(); // Register the iterator factory for arrays this.registerIteratorFactory( "arrayLike", m.isArrayLike, this.arrayLikeIter ); this.registerIteratorFactory( "iterateNext", this.hasIterateNext, this.iterateNextIter ); this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); }; MochiKit.Iter.__new__(); // // XXX: Internet Explorer blows // if (MochiKit.__export__) { reduce = MochiKit.Iter.reduce; } MochiKit.Base._exportSymbols(this, MochiKit.Iter); MochiKit-1.4.2/lib/MochiKit/DragAndDrop.js0000660000175000017500000006341511110670116017240 0ustar scottscott/*** MochiKit.DragAndDrop 1.4.2 See for documentation, downloads, license, etc. Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) Mochi-ized By Thomas Herve (_firstname_@nimail.org) ***/ MochiKit.Base._deps('DragAndDrop', ['Base', 'Iter', 'DOM', 'Signal', 'Visual', 'Position']); MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop'; MochiKit.DragAndDrop.VERSION = '1.4.2'; MochiKit.DragAndDrop.__repr__ = function () { return '[' + this.NAME + ' ' + this.VERSION + ']'; }; MochiKit.DragAndDrop.toString = function () { return this.__repr__(); }; MochiKit.DragAndDrop.EXPORT = [ "Droppable", "Draggable" ]; MochiKit.DragAndDrop.EXPORT_OK = [ "Droppables", "Draggables" ]; MochiKit.DragAndDrop.Droppables = { /*** Manage all droppables. Shouldn't be used, use the Droppable object instead. ***/ drops: [], remove: function (element) { this.drops = MochiKit.Base.filter(function (d) { return d.element != MochiKit.DOM.getElement(element); }, this.drops); }, register: function (drop) { this.drops.push(drop); }, unregister: function (drop) { this.drops = MochiKit.Base.filter(function (d) { return d != drop; }, this.drops); }, prepare: function (element) { MochiKit.Base.map(function (drop) { if (drop.isAccepted(element)) { if (drop.options.activeclass) { MochiKit.DOM.addElementClass(drop.element, drop.options.activeclass); } drop.options.onactive(drop.element, element); } }, this.drops); }, findDeepestChild: function (drops) { deepest = drops[0]; for (i = 1; i < drops.length; ++i) { if (MochiKit.DOM.isChildNode(drops[i].element, deepest.element)) { deepest = drops[i]; } } return deepest; }, show: function (point, element) { if (!this.drops.length) { return; } var affected = []; if (this.last_active) { this.last_active.deactivate(); } MochiKit.Iter.forEach(this.drops, function (drop) { if (drop.isAffected(point, element)) { affected.push(drop); } }); if (affected.length > 0) { drop = this.findDeepestChild(affected); MochiKit.Position.within(drop.element, point.page.x, point.page.y); drop.options.onhover(element, drop.element, MochiKit.Position.overlap(drop.options.overlap, drop.element)); drop.activate(); } }, fire: function (event, element) { if (!this.last_active) { return; } MochiKit.Position.prepare(); if (this.last_active.isAffected(event.mouse(), element)) { this.last_active.options.ondrop(element, this.last_active.element, event); } }, reset: function (element) { MochiKit.Base.map(function (drop) { if (drop.options.activeclass) { MochiKit.DOM.removeElementClass(drop.element, drop.options.activeclass); } drop.options.ondesactive(drop.element, element); }, this.drops); if (this.last_active) { this.last_active.deactivate(); } } }; /** @id MochiKit.DragAndDrop.Droppable */ MochiKit.DragAndDrop.Droppable = function (element, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(element, options); } this.__init__(element, options); }; MochiKit.DragAndDrop.Droppable.prototype = { /*** A droppable object. Simple use is to create giving an element: new MochiKit.DragAndDrop.Droppable('myelement'); Generally you'll want to define the 'ondrop' function and maybe the 'accept' option to filter draggables. ***/ __class__: MochiKit.DragAndDrop.Droppable, __init__: function (element, /* optional */options) { var d = MochiKit.DOM; var b = MochiKit.Base; this.element = d.getElement(element); this.options = b.update({ /** @id MochiKit.DragAndDrop.greedy */ greedy: true, /** @id MochiKit.DragAndDrop.hoverclass */ hoverclass: null, /** @id MochiKit.DragAndDrop.activeclass */ activeclass: null, /** @id MochiKit.DragAndDrop.hoverfunc */ hoverfunc: b.noop, /** @id MochiKit.DragAndDrop.accept */ accept: null, /** @id MochiKit.DragAndDrop.onactive */ onactive: b.noop, /** @id MochiKit.DragAndDrop.ondesactive */ ondesactive: b.noop, /** @id MochiKit.DragAndDrop.onhover */ onhover: b.noop, /** @id MochiKit.DragAndDrop.ondrop */ ondrop: b.noop, /** @id MochiKit.DragAndDrop.containment */ containment: [], tree: false }, options); // cache containers this.options._containers = []; b.map(MochiKit.Base.bind(function (c) { this.options._containers.push(d.getElement(c)); }, this), this.options.containment); MochiKit.Style.makePositioned(this.element); // fix IE MochiKit.DragAndDrop.Droppables.register(this); }, /** @id MochiKit.DragAndDrop.isContained */ isContained: function (element) { if (this.options._containers.length) { var containmentNode; if (this.options.tree) { containmentNode = element.treeNode; } else { containmentNode = element.parentNode; } return MochiKit.Iter.some(this.options._containers, function (c) { return containmentNode == c; }); } else { return true; } }, /** @id MochiKit.DragAndDrop.isAccepted */ isAccepted: function (element) { return ((!this.options.accept) || MochiKit.Iter.some( this.options.accept, function (c) { return MochiKit.DOM.hasElementClass(element, c); })); }, /** @id MochiKit.DragAndDrop.isAffected */ isAffected: function (point, element) { return ((this.element != element) && this.isContained(element) && this.isAccepted(element) && MochiKit.Position.within(this.element, point.page.x, point.page.y)); }, /** @id MochiKit.DragAndDrop.deactivate */ deactivate: function () { /*** A droppable is deactivate when a draggable has been over it and left. ***/ if (this.options.hoverclass) { MochiKit.DOM.removeElementClass(this.element, this.options.hoverclass); } this.options.hoverfunc(this.element, false); MochiKit.DragAndDrop.Droppables.last_active = null; }, /** @id MochiKit.DragAndDrop.activate */ activate: function () { /*** A droppable is active when a draggable is over it. ***/ if (this.options.hoverclass) { MochiKit.DOM.addElementClass(this.element, this.options.hoverclass); } this.options.hoverfunc(this.element, true); MochiKit.DragAndDrop.Droppables.last_active = this; }, /** @id MochiKit.DragAndDrop.destroy */ destroy: function () { /*** Delete this droppable. ***/ MochiKit.DragAndDrop.Droppables.unregister(this); }, /** @id MochiKit.DragAndDrop.repr */ repr: function () { return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]"; } }; MochiKit.DragAndDrop.Draggables = { /*** Manage draggables elements. Not intended to direct use. ***/ drags: [], register: function (draggable) { if (this.drags.length === 0) { var conn = MochiKit.Signal.connect; this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag); this.eventMouseMove = conn(document, 'onmousemove', this, this.updateDrag); this.eventKeypress = conn(document, 'onkeypress', this, this.keyPress); } this.drags.push(draggable); }, unregister: function (draggable) { this.drags = MochiKit.Base.filter(function (d) { return d != draggable; }, this.drags); if (this.drags.length === 0) { var disc = MochiKit.Signal.disconnect; disc(this.eventMouseUp); disc(this.eventMouseMove); disc(this.eventKeypress); } }, activate: function (draggable) { // allows keypress events if window is not currently focused // fails for Safari window.focus(); this.activeDraggable = draggable; }, deactivate: function () { this.activeDraggable = null; }, updateDrag: function (event) { if (!this.activeDraggable) { return; } var pointer = event.mouse(); // Mozilla-based browsers fire successive mousemove events with // the same coordinates, prevent needless redrawing (moz bug?) if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) == MochiKit.Base.repr(pointer.page))) { return; } this._lastPointer = pointer; this.activeDraggable.updateDrag(event, pointer); }, endDrag: function (event) { if (!this.activeDraggable) { return; } this._lastPointer = null; this.activeDraggable.endDrag(event); this.activeDraggable = null; }, keyPress: function (event) { if (this.activeDraggable) { this.activeDraggable.keyPress(event); } }, notify: function (eventName, draggable, event) { MochiKit.Signal.signal(this, eventName, draggable, event); } }; /** @id MochiKit.DragAndDrop.Draggable */ MochiKit.DragAndDrop.Draggable = function (element, options) { var cls = arguments.callee; if (!(this instanceof cls)) { return new cls(element, options); } this.__init__(element, options); }; MochiKit.DragAndDrop.Draggable.prototype = { /*** A draggable object. Simple instantiate : new MochiKit.DragAndDrop.Draggable('myelement'); ***/ __class__ : MochiKit.DragAndDrop.Draggable, __init__: function (element, /* optional */options) { var v = MochiKit.Visual; var b = MochiKit.Base; options = b.update({ /** @id MochiKit.DragAndDrop.handle */ handle: false, /** @id MochiKit.DragAndDrop.starteffect */ starteffect: function (innerelement) { this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0; new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7}); }, /** @id MochiKit.DragAndDrop.reverteffect */ reverteffect: function (innerelement, top_offset, left_offset) { var dur = Math.sqrt(Math.abs(top_offset^2) + Math.abs(left_offset^2))*0.02; return new v.Move(innerelement, {x: -left_offset, y: -top_offset, duration: dur}); }, /** @id MochiKit.DragAndDrop.endeffect */ endeffect: function (innerelement) { new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity}); }, /** @id MochiKit.DragAndDrop.onchange */ onchange: b.noop, /** @id MochiKit.DragAndDrop.zindex */ zindex: 1000, /** @id MochiKit.DragAndDrop.revert */ revert: false, /** @id MochiKit.DragAndDrop.scroll */ scroll: false, /** @id MochiKit.DragAndDrop.scrollSensitivity */ scrollSensitivity: 20, /** @id MochiKit.DragAndDrop.scrollSpeed */ scrollSpeed: 15, // false, or xy or [x, y] or function (x, y){return [x, y];} /** @id MochiKit.DragAndDrop.snap */ snap: false }, options); var d = MochiKit.DOM; this.element = d.getElement(element); if (options.handle && (typeof(options.handle) == 'string')) { this.handle = d.getFirstElementByTagAndClassName(null, options.handle, this.element); } if (!this.handle) { this.handle = d.getElement(options.handle); } if (!this.handle) { this.handle = this.element; } if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) { options.scroll = d.getElement(options.scroll); this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll); } MochiKit.Style.makePositioned(this.element); // fix IE this.delta = this.currentDelta(); this.options = options; this.dragging = false; this.eventMouseDown = MochiKit.Signal.connect(this.handle, 'onmousedown', this, this.initDrag); MochiKit.DragAndDrop.Draggables.register(this); }, /** @id MochiKit.DragAndDrop.destroy */ destroy: function () { MochiKit.Signal.disconnect(this.eventMouseDown); MochiKit.DragAndDrop.Draggables.unregister(this); }, /** @id MochiKit.DragAndDrop.currentDelta */ currentDelta: function () { var s = MochiKit.Style.getStyle; return [ parseInt(s(this.element, 'left') || '0'), parseInt(s(this.element, 'top') || '0')]; }, /** @id MochiKit.DragAndDrop.initDrag */ initDrag: function (event) { if (!event.mouse().button.left) { return; } // abort on form elements, fixes a Firefox issue var src = event.target(); var tagName = (src.tagName || '').toUpperCase(); if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'OPTION' || tagName === 'BUTTON' || tagName === 'TEXTAREA') { return; } if (this._revert) { this._revert.cancel(); this._revert = null; } var pointer = event.mouse(); var pos = MochiKit.Position.cumulativeOffset(this.element); this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y]; MochiKit.DragAndDrop.Draggables.activate(this); event.stop(); }, /** @id MochiKit.DragAndDrop.startDrag */ startDrag: function (event) { this.dragging = true; if (this.options.selectclass) { MochiKit.DOM.addElementClass(this.element, this.options.selectclass); } if (this.options.zindex) { this.originalZ = parseInt(MochiKit.Style.getStyle(this.element, 'z-index') || '0'); this.element.style.zIndex = this.options.zindex; } if (this.options.ghosting) { this._clone = this.element.cloneNode(true); this.ghostPosition = MochiKit.Position.absolutize(this.element); this.element.parentNode.insertBefore(this._clone, this.element); } if (this.options.scroll) { if (this.options.scroll == window) { var where = this._getWindowScroll(this.options.scroll); this.originalScrollLeft = where.left; this.originalScrollTop = where.top; } else { this.originalScrollLeft = this.options.scroll.scrollLeft; this.originalScrollTop = this.options.scroll.scrollTop; } } MochiKit.DragAndDrop.Droppables.prepare(this.element); MochiKit.DragAndDrop.Draggables.notify('start', this, event); if (this.options.starteffect) { this.options.starteffect(this.element); } }, /** @id MochiKit.DragAndDrop.updateDrag */ updateDrag: function (event, pointer) { if (!this.dragging) { this.startDrag(event); } MochiKit.Position.prepare(); MochiKit.DragAndDrop.Droppables.show(pointer, this.element); MochiKit.DragAndDrop.Draggables.notify('drag', this, event); this.draw(pointer); this.options.onchange(this); if (this.options.scroll) { this.stopScrolling(); var p, q; if (this.options.scroll == window) { var s = this._getWindowScroll(this.options.scroll); p = new MochiKit.Style.Coordinates(s.left, s.top); q = new MochiKit.Style.Coordinates(s.left + s.width, s.top + s.height); } else { p = MochiKit.Position.page(this.options.scroll); p.x += this.options.scroll.scrollLeft; p.y += this.options.scroll.scrollTop; p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0); p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0); q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth, p.y + this.options.scroll.offsetHeight); } var speed = [0, 0]; if (pointer.page.x > (q.x - this.options.scrollSensitivity)) { speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity); } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) { speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity); } if (pointer.page.y > (q.y - this.options.scrollSensitivity)) { speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity); } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) { speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity); } this.startScrolling(speed); } // fix AppleWebKit rendering if (/AppleWebKit/.test(navigator.appVersion)) { window.scrollBy(0, 0); } event.stop(); }, /** @id MochiKit.DragAndDrop.finishDrag */ finishDrag: function (event, success) { var dr = MochiKit.DragAndDrop; this.dragging = false; if (this.options.selectclass) { MochiKit.DOM.removeElementClass(this.element, this.options.selectclass); } if (this.options.ghosting) { // XXX: from a user point of view, it would be better to remove // the node only *after* the MochiKit.Visual.Move end when used // with revert. MochiKit.Position.relativize(this.element, this.ghostPosition); MochiKit.DOM.removeElement(this._clone); this._clone = null; } if (success) { dr.Droppables.fire(event, this.element); } dr.Draggables.notify('end', this, event); var revert = this.options.revert; if (revert && typeof(revert) == 'function') { revert = revert(this.element); } var d = this.currentDelta(); if (revert && this.options.reverteffect) { this._revert = this.options.reverteffect(this.element, d[1] - this.delta[1], d[0] - this.delta[0]); } else { this.delta = d; } if (this.options.zindex) { this.element.style.zIndex = this.originalZ; } if (this.options.endeffect) { this.options.endeffect(this.element); } dr.Draggables.deactivate(); dr.Droppables.reset(this.element); }, /** @id MochiKit.DragAndDrop.keyPress */ keyPress: function (event) { if (event.key().string != "KEY_ESCAPE") { return; } this.finishDrag(event, false); event.stop(); }, /** @id MochiKit.DragAndDrop.endDrag */ endDrag: function (event) { if (!this.dragging) { return; } this.stopScrolling(); this.finishDrag(event, true); event.stop(); }, /** @id MochiKit.DragAndDrop.draw */ draw: function (point) { var pos = MochiKit.Position.cumulativeOffset(this.element); var d = this.currentDelta(); pos.x -= d[0]; pos.y -= d[1]; if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) { pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft; pos.y -= this.options.scroll.scrollTop - this.originalScrollTop; } var p = [point.page.x - pos.x - this.offset[0], point.page.y - pos.y - this.offset[1]]; if (this.options.snap) { if (typeof(this.options.snap) == 'function') { p = this.options.snap(p[0], p[1]); } else { if (this.options.snap instanceof Array) { var i = -1; p = MochiKit.Base.map(MochiKit.Base.bind(function (v) { i += 1; return Math.round(v/this.options.snap[i]) * this.options.snap[i]; }, this), p); } else { p = MochiKit.Base.map(MochiKit.Base.bind(function (v) { return Math.round(v/this.options.snap) * this.options.snap; }, this), p); } } } var style = this.element.style; if ((!this.options.constraint) || (this.options.constraint == 'horizontal')) { style.left = p[0] + 'px'; } if ((!this.options.constraint) || (this.options.constraint == 'vertical')) { style.top = p[1] + 'px'; } if (style.visibility == 'hidden') { style.visibility = ''; // fix gecko rendering } }, /** @id MochiKit.DragAndDrop.stopScrolling */ stopScrolling: function () { if (this.scrollInterval) { clearInterval(this.scrollInterval); this.scrollInterval = null; MochiKit.DragAndDrop.Draggables._lastScrollPointer = null; } }, /** @id MochiKit.DragAndDrop.startScrolling */ startScrolling: function (speed) { if (!speed[0] && !speed[1]) { return; } this.scrollSpeed = [speed[0] * this.options.scrollSpeed, speed[1] * this.options.scrollSpeed]; this.lastScrolled = new Date(); this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10); }, /** @id MochiKit.DragAndDrop.scroll */ scroll: function () { var current = new Date(); var delta = current - this.lastScrolled; this.lastScrolled = current; if (this.options.scroll == window) { var s = this._getWindowScroll(this.options.scroll); if (this.scrollSpeed[0] || this.scrollSpeed[1]) { var dm = delta / 1000; this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0], s.top + dm * this.scrollSpeed[1]); } } else { this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000; this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000; } var d = MochiKit.DragAndDrop; MochiKit.Position.prepare(); d.Droppables.show(d.Draggables._lastPointer, this.element); d.Draggables.notify('drag', this); if (this._isScrollChild) { d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer; d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000; d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000; if (d.Draggables._lastScrollPointer.x < 0) { d.Draggables._lastScrollPointer.x = 0; } if (d.Draggables._lastScrollPointer.y < 0) { d.Draggables._lastScrollPointer.y = 0; } this.draw(d.Draggables._lastScrollPointer); } this.options.onchange(this); }, _getWindowScroll: function (win) { var vp, w, h; MochiKit.DOM.withWindow(win, function () { vp = MochiKit.Style.getViewportPosition(win.document); }); if (win.innerWidth) { w = win.innerWidth; h = win.innerHeight; } else if (win.document.documentElement && win.document.documentElement.clientWidth) { w = win.document.documentElement.clientWidth; h = win.document.documentElement.clientHeight; } else { w = win.document.body.offsetWidth; h = win.document.body.offsetHeight; } return {top: vp.y, left: vp.x, width: w, height: h}; }, /** @id MochiKit.DragAndDrop.repr */ repr: function () { return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]"; } }; MochiKit.DragAndDrop.__new__ = function () { MochiKit.Base.nameFunctions(this); this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK) }; }; MochiKit.DragAndDrop.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop); MochiKit-1.4.2/lib/MochiKit/Position.js0000660000175000017500000001671511110666344016730 0ustar scottscott/*** MochiKit.Position 1.4.2 See for documentation, downloads, license, etc. (c) 2005-2006 Bob Ippolito and others. All rights Reserved. ***/ MochiKit.Base._deps('Position', ['Base', 'DOM', 'Style']); MochiKit.Position.NAME = 'MochiKit.Position'; MochiKit.Position.VERSION = '1.4.2'; MochiKit.Position.__repr__ = function () { return '[' + this.NAME + ' ' + this.VERSION + ']'; }; MochiKit.Position.toString = function () { return this.__repr__(); }; MochiKit.Position.EXPORT_OK = []; MochiKit.Position.EXPORT = [ ]; MochiKit.Base.update(MochiKit.Position, { // set to true if needed, warning: firefox performance problems // NOT neeeded for page scrolling, only if draggable contained in // scrollable elements includeScrollOffsets: false, /** @id MochiKit.Position.prepare */ prepare: function () { var deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; var deltaY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY); }, /** @id MochiKit.Position.cumulativeOffset */ cumulativeOffset: function (element) { var valueT = 0; var valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return new MochiKit.Style.Coordinates(valueL, valueT); }, /** @id MochiKit.Position.realOffset */ realOffset: function (element) { var valueT = 0; var valueL = 0; do { valueT += element.scrollTop || 0; valueL += element.scrollLeft || 0; element = element.parentNode; } while (element); return new MochiKit.Style.Coordinates(valueL, valueT); }, /** @id MochiKit.Position.within */ 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); if (element.style.position == "fixed") { this.offset.x += this.windowOffset.x; this.offset.y += this.windowOffset.y; } return (y >= this.offset.y && y < this.offset.y + element.offsetHeight && x >= this.offset.x && x < this.offset.x + element.offsetWidth); }, /** @id MochiKit.Position.withinIncludingScrolloffsets */ withinIncludingScrolloffsets: function (element, x, y) { var offsetcache = this.realOffset(element); this.xcomp = x + offsetcache.x - this.windowOffset.x; this.ycomp = y + offsetcache.y - this.windowOffset.y; this.offset = this.cumulativeOffset(element); return (this.ycomp >= this.offset.y && this.ycomp < this.offset.y + element.offsetHeight && this.xcomp >= this.offset.x && this.xcomp < this.offset.x + element.offsetWidth); }, // within must be called directly before /** @id MochiKit.Position.overlap */ overlap: function (mode, element) { if (!mode) { return 0; } if (mode == 'vertical') { return ((this.offset.y + element.offsetHeight) - this.ycomp) / element.offsetHeight; } if (mode == 'horizontal') { return ((this.offset.x + element.offsetWidth) - this.xcomp) / element.offsetWidth; } }, /** @id MochiKit.Position.absolutize */ absolutize: function (element) { element = MochiKit.DOM.getElement(element); if (element.style.position == 'absolute') { return; } MochiKit.Position.prepare(); var offsets = MochiKit.Position.positionedOffset(element); var width = element.clientWidth; var height = element.clientHeight; var oldStyle = { 'position': element.style.position, 'left': offsets.x - parseFloat(element.style.left || 0), 'top': offsets.y - parseFloat(element.style.top || 0), 'width': element.style.width, 'height': element.style.height }; element.style.position = 'absolute'; element.style.top = offsets.y + 'px'; element.style.left = offsets.x + 'px'; element.style.width = width + 'px'; element.style.height = height + 'px'; return oldStyle; }, /** @id MochiKit.Position.positionedOffset */ positionedOffset: function (element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { p = MochiKit.Style.getStyle(element, 'position'); if (p == 'relative' || p == 'absolute') { break; } } } while (element); return new MochiKit.Style.Coordinates(valueL, valueT); }, /** @id MochiKit.Position.relativize */ relativize: function (element, oldPos) { element = MochiKit.DOM.getElement(element); if (element.style.position == 'relative') { return; } MochiKit.Position.prepare(); var top = parseFloat(element.style.top || 0) - (oldPos['top'] || 0); var left = parseFloat(element.style.left || 0) - (oldPos['left'] || 0); element.style.position = oldPos['position']; element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.width = oldPos['width']; element.style.height = oldPos['height']; }, /** @id MochiKit.Position.clone */ clone: function (source, target) { source = MochiKit.DOM.getElement(source); target = MochiKit.DOM.getElement(target); target.style.position = 'absolute'; var offsets = this.cumulativeOffset(source); target.style.top = offsets.y + 'px'; target.style.left = offsets.x + 'px'; target.style.width = source.offsetWidth + 'px'; target.style.height = source.offsetHeight + 'px'; }, /** @id MochiKit.Position.page */ page: function (forElement) { var valueT = 0; var valueL = 0; var element = forElement; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; // Safari fix if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') { break; } } while (element = element.offsetParent); element = forElement; do { valueT -= element.scrollTop || 0; valueL -= element.scrollLeft || 0; } while (element = element.parentNode); return new MochiKit.Style.Coordinates(valueL, valueT); } }); MochiKit.Position.__new__ = function (win) { var m = MochiKit.Base; this.EXPORT_TAGS = { ':common': this.EXPORT, ':all': m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); }; MochiKit.Position.__new__(this); MochiKit.Base._exportSymbols(this, MochiKit.Position); MochiKit-1.4.2/lib/MochiKit/DateTime.js0000660000175000017500000001433711110670142016605 0ustar scottscott/*** MochiKit.DateTime 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('DateTime', ['Base']); MochiKit.DateTime.NAME = "MochiKit.DateTime"; MochiKit.DateTime.VERSION = "1.4.2"; MochiKit.DateTime.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.DateTime.toString = function () { return this.__repr__(); }; /** @id MochiKit.DateTime.isoDate */ MochiKit.DateTime.isoDate = function (str) { str = str + ""; if (typeof(str) != "string" || str.length === 0) { return null; } var iso = str.split('-'); if (iso.length === 0) { return null; } var date = new Date(iso[0], iso[1] - 1, iso[2]); date.setFullYear(iso[0]); date.setMonth(iso[1] - 1); date.setDate(iso[2]); return date; }; MochiKit.DateTime._isoRegexp = /(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/; /** @id MochiKit.DateTime.isoTimestamp */ MochiKit.DateTime.isoTimestamp = function (str) { str = str + ""; if (typeof(str) != "string" || str.length === 0) { return null; } var res = str.match(MochiKit.DateTime._isoRegexp); if (typeof(res) == "undefined" || res === null) { return null; } var year, month, day, hour, min, sec, msec; year = parseInt(res[1], 10); if (typeof(res[2]) == "undefined" || res[2] === '') { return new Date(year); } month = parseInt(res[2], 10) - 1; day = parseInt(res[3], 10); if (typeof(res[4]) == "undefined" || res[4] === '') { return new Date(year, month, day); } hour = parseInt(res[4], 10); min = parseInt(res[5], 10); sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0; if (typeof(res[7]) != "undefined" && res[7] !== '') { msec = Math.round(1000.0 * parseFloat("0." + res[7])); } else { msec = 0; } if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) { return new Date(year, month, day, hour, min, sec, msec); } var ofs; if (typeof(res[9]) != "undefined" && res[9] !== '') { ofs = parseInt(res[10], 10) * 3600000; if (typeof(res[11]) != "undefined" && res[11] !== '') { ofs += parseInt(res[11], 10) * 60000; } if (res[9] == "-") { ofs = -ofs; } } else { ofs = 0; } return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs); }; /** @id MochiKit.DateTime.toISOTime */ MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) { if (typeof(date) == "undefined" || date === null) { return null; } var hh = date.getHours(); var mm = date.getMinutes(); var ss = date.getSeconds(); var lst = [ ((realISO && (hh < 10)) ? "0" + hh : hh), ((mm < 10) ? "0" + mm : mm), ((ss < 10) ? "0" + ss : ss) ]; return lst.join(":"); }; /** @id MochiKit.DateTime.toISOTimeStamp */ MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) { if (typeof(date) == "undefined" || date === null) { return null; } var sep = realISO ? "T" : " "; var foot = realISO ? "Z" : ""; if (realISO) { date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000)); } return MochiKit.DateTime.toISODate(date) + sep + MochiKit.DateTime.toISOTime(date, realISO) + foot; }; /** @id MochiKit.DateTime.toISODate */ MochiKit.DateTime.toISODate = function (date) { if (typeof(date) == "undefined" || date === null) { return null; } var _padTwo = MochiKit.DateTime._padTwo; var _padFour = MochiKit.DateTime._padFour; return [ _padFour(date.getFullYear()), _padTwo(date.getMonth() + 1), _padTwo(date.getDate()) ].join("-"); }; /** @id MochiKit.DateTime.americanDate */ MochiKit.DateTime.americanDate = function (d) { d = d + ""; if (typeof(d) != "string" || d.length === 0) { return null; } var a = d.split('/'); return new Date(a[2], a[0] - 1, a[1]); }; MochiKit.DateTime._padTwo = function (n) { return (n > 9) ? n : "0" + n; }; MochiKit.DateTime._padFour = function(n) { switch(n.toString().length) { case 1: return "000" + n; break; case 2: return "00" + n; break; case 3: return "0" + n; break; case 4: default: return n; } }; /** @id MochiKit.DateTime.toPaddedAmericanDate */ MochiKit.DateTime.toPaddedAmericanDate = function (d) { if (typeof(d) == "undefined" || d === null) { return null; } var _padTwo = MochiKit.DateTime._padTwo; return [ _padTwo(d.getMonth() + 1), _padTwo(d.getDate()), d.getFullYear() ].join('/'); }; /** @id MochiKit.DateTime.toAmericanDate */ MochiKit.DateTime.toAmericanDate = function (d) { if (typeof(d) == "undefined" || d === null) { return null; } return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/'); }; MochiKit.DateTime.EXPORT = [ "isoDate", "isoTimestamp", "toISOTime", "toISOTimestamp", "toISODate", "americanDate", "toPaddedAmericanDate", "toAmericanDate" ]; MochiKit.DateTime.EXPORT_OK = []; MochiKit.DateTime.EXPORT_TAGS = { ":common": MochiKit.DateTime.EXPORT, ":all": MochiKit.DateTime.EXPORT }; MochiKit.DateTime.__new__ = function () { // MochiKit.Base.nameFunctions(this); var base = this.NAME + "."; for (var k in this) { var o = this[k]; if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') { try { o.NAME = base + k; } catch (e) { // pass } } } }; MochiKit.DateTime.__new__(); if (typeof(MochiKit.Base) != "undefined") { MochiKit.Base._exportSymbols(this, MochiKit.DateTime); } else { (function (globals, module) { if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined') || (MochiKit.__export__ === false)) { var all = module.EXPORT_TAGS[":all"]; for (var i = 0; i < all.length; i++) { globals[all[i]] = module[all[i]]; } } })(this, MochiKit.DateTime); } MochiKit-1.4.2/lib/MochiKit/Signal.js0000660000175000017500000007075311110666326016343 0ustar scottscott/*** MochiKit.Signal 1.4.2 See for documentation, downloads, license, etc. (c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('Signal', ['Base', 'DOM', 'Style']); MochiKit.Signal.NAME = 'MochiKit.Signal'; MochiKit.Signal.VERSION = '1.4.2'; MochiKit.Signal._observers = []; /** @id MochiKit.Signal.Event */ MochiKit.Signal.Event = function (src, e) { this._event = e || window.event; this._src = src; }; MochiKit.Base.update(MochiKit.Signal.Event.prototype, { __repr__: function () { var repr = MochiKit.Base.repr; var str = '{event(): ' + repr(this.event()) + ', src(): ' + repr(this.src()) + ', type(): ' + repr(this.type()) + ', target(): ' + repr(this.target()); if (this.type() && this.type().indexOf('key') === 0 || this.type().indexOf('mouse') === 0 || this.type().indexOf('click') != -1 || this.type() == 'contextmenu') { str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) + ', ctrl: ' + repr(this.modifier().ctrl) + ', meta: ' + repr(this.modifier().meta) + ', shift: ' + repr(this.modifier().shift) + ', any: ' + repr(this.modifier().any) + '}'; } if (this.type() && this.type().indexOf('key') === 0) { str += ', key(): {code: ' + repr(this.key().code) + ', string: ' + repr(this.key().string) + '}'; } if (this.type() && ( this.type().indexOf('mouse') === 0 || this.type().indexOf('click') != -1 || this.type() == 'contextmenu')) { str += ', mouse(): {page: ' + repr(this.mouse().page) + ', client: ' + repr(this.mouse().client); if (this.type() != 'mousemove' && this.type() != 'mousewheel') { str += ', button: {left: ' + repr(this.mouse().button.left) + ', middle: ' + repr(this.mouse().button.middle) + ', right: ' + repr(this.mouse().button.right) + '}'; } if (this.type() == 'mousewheel') { str += ', wheel: ' + repr(this.mouse().wheel); } str += '}'; } if (this.type() == 'mouseover' || this.type() == 'mouseout' || this.type() == 'mouseenter' || this.type() == 'mouseleave') { str += ', relatedTarget(): ' + repr(this.relatedTarget()); } str += '}'; return str; }, /** @id MochiKit.Signal.Event.prototype.toString */ toString: function () { return this.__repr__(); }, /** @id MochiKit.Signal.Event.prototype.src */ src: function () { return this._src; }, /** @id MochiKit.Signal.Event.prototype.event */ event: function () { return this._event; }, /** @id MochiKit.Signal.Event.prototype.type */ type: function () { if (this._event.type === "DOMMouseScroll") { return "mousewheel"; } else { return this._event.type || undefined; } }, /** @id MochiKit.Signal.Event.prototype.target */ target: function () { return this._event.target || this._event.srcElement; }, _relatedTarget: null, /** @id MochiKit.Signal.Event.prototype.relatedTarget */ relatedTarget: function () { if (this._relatedTarget !== null) { return this._relatedTarget; } var elem = null; if (this.type() == 'mouseover' || this.type() == 'mouseenter') { elem = (this._event.relatedTarget || this._event.fromElement); } else if (this.type() == 'mouseout' || this.type() == 'mouseleave') { elem = (this._event.relatedTarget || this._event.toElement); } try { if (elem !== null && elem.nodeType !== null) { this._relatedTarget = elem; return elem; } } catch (ignore) { // Firefox 3 throws a permission denied error when accessing // any property on XUL elements (e.g. scrollbars)... } return undefined; }, _modifier: null, /** @id MochiKit.Signal.Event.prototype.modifier */ modifier: function () { if (this._modifier !== null) { return this._modifier; } var m = {}; m.alt = this._event.altKey; m.ctrl = this._event.ctrlKey; m.meta = this._event.metaKey || false; // IE and Opera punt here m.shift = this._event.shiftKey; m.any = m.alt || m.ctrl || m.shift || m.meta; this._modifier = m; return m; }, _key: null, /** @id MochiKit.Signal.Event.prototype.key */ key: function () { if (this._key !== null) { return this._key; } var k = {}; if (this.type() && this.type().indexOf('key') === 0) { /* If you're looking for a special key, look for it in keydown or keyup, but never keypress. If you're looking for a Unicode chracter, look for it with keypress, but never keyup or keydown. Notes: FF key event behavior: key event charCode keyCode DOWN ku,kd 0 40 DOWN kp 0 40 ESC ku,kd 0 27 ESC kp 0 27 a ku,kd 0 65 a kp 97 0 shift+a ku,kd 0 65 shift+a kp 65 0 1 ku,kd 0 49 1 kp 49 0 shift+1 ku,kd 0 0 shift+1 kp 33 0 IE key event behavior: (IE doesn't fire keypress events for special keys.) key event keyCode DOWN ku,kd 40 DOWN kp undefined ESC ku,kd 27 ESC kp 27 a ku,kd 65 a kp 97 shift+a ku,kd 65 shift+a kp 65 1 ku,kd 49 1 kp 49 shift+1 ku,kd 49 shift+1 kp 33 Safari key event behavior: (Safari sets charCode and keyCode to something crazy for special keys.) key event charCode keyCode DOWN ku,kd 63233 40 DOWN kp 63233 63233 ESC ku,kd 27 27 ESC kp 27 27 a ku,kd 97 65 a kp 97 97 shift+a ku,kd 65 65 shift+a kp 65 65 1 ku,kd 49 49 1 kp 49 49 shift+1 ku,kd 33 49 shift+1 kp 33 33 */ /* look for special keys here */ if (this.type() == 'keydown' || this.type() == 'keyup') { k.code = this._event.keyCode; k.string = (MochiKit.Signal._specialKeys[k.code] || 'KEY_UNKNOWN'); this._key = k; return k; /* look for characters here */ } else if (this.type() == 'keypress') { /* Special key behavior: IE: does not fire keypress events for special keys FF: sets charCode to 0, and sets the correct keyCode Safari: sets keyCode and charCode to something stupid */ k.code = 0; k.string = ''; if (typeof(this._event.charCode) != 'undefined' && this._event.charCode !== 0 && !MochiKit.Signal._specialMacKeys[this._event.charCode]) { k.code = this._event.charCode; k.string = String.fromCharCode(k.code); } else if (this._event.keyCode && typeof(this._event.charCode) == 'undefined') { // IE k.code = this._event.keyCode; k.string = String.fromCharCode(k.code); } this._key = k; return k; } } return undefined; }, _mouse: null, /** @id MochiKit.Signal.Event.prototype.mouse */ mouse: function () { if (this._mouse !== null) { return this._mouse; } var m = {}; var e = this._event; if (this.type() && ( this.type().indexOf('mouse') === 0 || this.type().indexOf('click') != -1 || this.type() == 'contextmenu')) { m.client = new MochiKit.Style.Coordinates(0, 0); if (e.clientX || e.clientY) { m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX; m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY; } m.page = new MochiKit.Style.Coordinates(0, 0); if (e.pageX || e.pageY) { m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX; m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY; } else { /* The IE shortcut can be off by two. We fix it. See: http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp This is similar to the method used in MochiKit.Style.getElementPosition(). */ var de = MochiKit.DOM._document.documentElement; var b = MochiKit.DOM._document.body; m.page.x = e.clientX + (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0); m.page.y = e.clientY + (de.scrollTop || b.scrollTop) - (de.clientTop || 0); } if (this.type() != 'mousemove' && this.type() != 'mousewheel') { m.button = {}; m.button.left = false; m.button.right = false; m.button.middle = false; /* we could check e.button, but which is more consistent */ if (e.which) { m.button.left = (e.which == 1); m.button.middle = (e.which == 2); m.button.right = (e.which == 3); /* Mac browsers and right click: - Safari doesn't fire any click events on a right click: http://bugs.webkit.org/show_bug.cgi?id=6595 - Firefox fires the event, and sets ctrlKey = true - Opera fires the event, and sets metaKey = true oncontextmenu is fired on right clicks between browsers and across platforms. */ } else { m.button.left = !!(e.button & 1); m.button.right = !!(e.button & 2); m.button.middle = !!(e.button & 4); } } if (this.type() == 'mousewheel') { m.wheel = new MochiKit.Style.Coordinates(0, 0); if (e.wheelDeltaX || e.wheelDeltaY) { m.wheel.x = e.wheelDeltaX / -40 || 0; m.wheel.y = e.wheelDeltaY / -40 || 0; } else if (e.wheelDelta) { m.wheel.y = e.wheelDelta / -40; } else { m.wheel.y = e.detail || 0; } } this._mouse = m; return m; } return undefined; }, /** @id MochiKit.Signal.Event.prototype.stop */ stop: function () { this.stopPropagation(); this.preventDefault(); }, /** @id MochiKit.Signal.Event.prototype.stopPropagation */ stopPropagation: function () { if (this._event.stopPropagation) { this._event.stopPropagation(); } else { this._event.cancelBubble = true; } }, /** @id MochiKit.Signal.Event.prototype.preventDefault */ preventDefault: function () { if (this._event.preventDefault) { this._event.preventDefault(); } else if (this._confirmUnload === null) { this._event.returnValue = false; } }, _confirmUnload: null, /** @id MochiKit.Signal.Event.prototype.confirmUnload */ confirmUnload: function (msg) { if (this.type() == 'beforeunload') { this._confirmUnload = msg; this._event.returnValue = msg; } } }); /* Safari sets keyCode to these special values onkeypress. */ MochiKit.Signal._specialMacKeys = { 3: 'KEY_ENTER', 63289: 'KEY_NUM_PAD_CLEAR', 63276: 'KEY_PAGE_UP', 63277: 'KEY_PAGE_DOWN', 63275: 'KEY_END', 63273: 'KEY_HOME', 63234: 'KEY_ARROW_LEFT', 63232: 'KEY_ARROW_UP', 63235: 'KEY_ARROW_RIGHT', 63233: 'KEY_ARROW_DOWN', 63302: 'KEY_INSERT', 63272: 'KEY_DELETE' }; /* for KEY_F1 - KEY_F12 */ (function () { var _specialMacKeys = MochiKit.Signal._specialMacKeys; for (i = 63236; i <= 63242; i++) { // no F0 _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1); } })(); /* Standard keyboard key codes. */ MochiKit.Signal._specialKeys = { 8: 'KEY_BACKSPACE', 9: 'KEY_TAB', 12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only 13: 'KEY_ENTER', 16: 'KEY_SHIFT', 17: 'KEY_CTRL', 18: 'KEY_ALT', 19: 'KEY_PAUSE', 20: 'KEY_CAPS_LOCK', 27: 'KEY_ESCAPE', 32: 'KEY_SPACEBAR', 33: 'KEY_PAGE_UP', 34: 'KEY_PAGE_DOWN', 35: 'KEY_END', 36: 'KEY_HOME', 37: 'KEY_ARROW_LEFT', 38: 'KEY_ARROW_UP', 39: 'KEY_ARROW_RIGHT', 40: 'KEY_ARROW_DOWN', 44: 'KEY_PRINT_SCREEN', 45: 'KEY_INSERT', 46: 'KEY_DELETE', 59: 'KEY_SEMICOLON', // weird, for Safari and IE only 91: 'KEY_WINDOWS_LEFT', 92: 'KEY_WINDOWS_RIGHT', 93: 'KEY_SELECT', 106: 'KEY_NUM_PAD_ASTERISK', 107: 'KEY_NUM_PAD_PLUS_SIGN', 109: 'KEY_NUM_PAD_HYPHEN-MINUS', 110: 'KEY_NUM_PAD_FULL_STOP', 111: 'KEY_NUM_PAD_SOLIDUS', 144: 'KEY_NUM_LOCK', 145: 'KEY_SCROLL_LOCK', 186: 'KEY_SEMICOLON', 187: 'KEY_EQUALS_SIGN', 188: 'KEY_COMMA', 189: 'KEY_HYPHEN-MINUS', 190: 'KEY_FULL_STOP', 191: 'KEY_SOLIDUS', 192: 'KEY_GRAVE_ACCENT', 219: 'KEY_LEFT_SQUARE_BRACKET', 220: 'KEY_REVERSE_SOLIDUS', 221: 'KEY_RIGHT_SQUARE_BRACKET', 222: 'KEY_APOSTROPHE' // undefined: 'KEY_UNKNOWN' }; (function () { /* for KEY_0 - KEY_9 */ var _specialKeys = MochiKit.Signal._specialKeys; for (var i = 48; i <= 57; i++) { _specialKeys[i] = 'KEY_' + (i - 48); } /* for KEY_A - KEY_Z */ for (i = 65; i <= 90; i++) { _specialKeys[i] = 'KEY_' + String.fromCharCode(i); } /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */ for (i = 96; i <= 105; i++) { _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96); } /* for KEY_F1 - KEY_F12 */ for (i = 112; i <= 123; i++) { // no F0 _specialKeys[i] = 'KEY_F' + (i - 112 + 1); } })(); /* Internal object to keep track of created signals. */ MochiKit.Signal.Ident = function (ident) { this.source = ident.source; this.signal = ident.signal; this.listener = ident.listener; this.isDOM = ident.isDOM; this.objOrFunc = ident.objOrFunc; this.funcOrStr = ident.funcOrStr; this.connected = ident.connected; }; MochiKit.Signal.Ident.prototype = {}; MochiKit.Base.update(MochiKit.Signal, { __repr__: function () { return '[' + this.NAME + ' ' + this.VERSION + ']'; }, toString: function () { return this.__repr__(); }, _unloadCache: function () { var self = MochiKit.Signal; var observers = self._observers; for (var i = 0; i < observers.length; i++) { if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') { self._disconnect(observers[i]); } } }, _listener: function (src, sig, func, obj, isDOM) { var self = MochiKit.Signal; var E = self.Event; if (!isDOM) { /* We don't want to re-bind already bound methods */ if (typeof(func.im_self) == 'undefined') { return MochiKit.Base.bindLate(func, obj); } else { return func; } } obj = obj || src; if (typeof(func) == "string") { if (sig === 'onload' || sig === 'onunload') { return function (nativeEvent) { obj[func].apply(obj, [new E(src, nativeEvent)]); var ident = new MochiKit.Signal.Ident({ source: src, signal: sig, objOrFunc: obj, funcOrStr: func}); MochiKit.Signal._disconnect(ident); }; } else { return function (nativeEvent) { obj[func].apply(obj, [new E(src, nativeEvent)]); }; } } else { if (sig === 'onload' || sig === 'onunload') { return function (nativeEvent) { func.apply(obj, [new E(src, nativeEvent)]); var ident = new MochiKit.Signal.Ident({ source: src, signal: sig, objOrFunc: func}); MochiKit.Signal._disconnect(ident); }; } else { return function (nativeEvent) { func.apply(obj, [new E(src, nativeEvent)]); }; } } }, _browserAlreadyHasMouseEnterAndLeave: function () { return /MSIE/.test(navigator.userAgent); }, _browserLacksMouseWheelEvent: function () { return /Gecko\//.test(navigator.userAgent); }, _mouseEnterListener: function (src, sig, func, obj) { var E = MochiKit.Signal.Event; return function (nativeEvent) { var e = new E(src, nativeEvent); try { e.relatedTarget().nodeName; } catch (err) { /* probably hit a permission denied error; possibly one of * firefox's screwy anonymous DIVs inside an input element. * Allow this event to propogate up. */ return; } e.stop(); if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) { /* We've moved between our node and a child. Ignore. */ return; } e.type = function () { return sig; }; if (typeof(func) == "string") { return obj[func].apply(obj, [e]); } else { return func.apply(obj, [e]); } }; }, _getDestPair: function (objOrFunc, funcOrStr) { var obj = null; var func = null; if (typeof(funcOrStr) != 'undefined') { obj = objOrFunc; func = funcOrStr; if (typeof(funcOrStr) == 'string') { if (typeof(objOrFunc[funcOrStr]) != "function") { throw new Error("'funcOrStr' must be a function on 'objOrFunc'"); } } else if (typeof(funcOrStr) != 'function') { throw new Error("'funcOrStr' must be a function or string"); } } else if (typeof(objOrFunc) != "function") { throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given"); } else { func = objOrFunc; } return [obj, func]; }, /** @id MochiKit.Signal.connect */ connect: function (src, sig, objOrFunc/* optional */, funcOrStr) { src = MochiKit.DOM.getElement(src); var self = MochiKit.Signal; if (typeof(sig) != 'string') { throw new Error("'sig' must be a string"); } var destPair = self._getDestPair(objOrFunc, funcOrStr); var obj = destPair[0]; var func = destPair[1]; if (typeof(obj) == 'undefined' || obj === null) { obj = src; } var isDOM = !!(src.addEventListener || src.attachEvent); if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave") && !self._browserAlreadyHasMouseEnterAndLeave()) { var listener = self._mouseEnterListener(src, sig.substr(2), func, obj); if (sig === "onmouseenter") { sig = "onmouseover"; } else { sig = "onmouseout"; } } else if (isDOM && sig == "onmousewheel" && self._browserLacksMouseWheelEvent()) { var listener = self._listener(src, sig, func, obj, isDOM); sig = "onDOMMouseScroll"; } else { var listener = self._listener(src, sig, func, obj, isDOM); } if (src.addEventListener) { src.addEventListener(sig.substr(2), listener, false); } else if (src.attachEvent) { src.attachEvent(sig, listener); // useCapture unsupported } var ident = new MochiKit.Signal.Ident({ source: src, signal: sig, listener: listener, isDOM: isDOM, objOrFunc: objOrFunc, funcOrStr: funcOrStr, connected: true }); self._observers.push(ident); if (!isDOM && typeof(src.__connect__) == 'function') { var args = MochiKit.Base.extend([ident], arguments, 1); src.__connect__.apply(src, args); } return ident; }, _disconnect: function (ident) { // already disconnected if (!ident.connected) { return; } ident.connected = false; var src = ident.source; var sig = ident.signal; var listener = ident.listener; // check isDOM if (!ident.isDOM) { if (typeof(src.__disconnect__) == 'function') { src.__disconnect__(ident, sig, ident.objOrFunc, ident.funcOrStr); } return; } if (src.removeEventListener) { src.removeEventListener(sig.substr(2), listener, false); } else if (src.detachEvent) { src.detachEvent(sig, listener); // useCapture unsupported } else { throw new Error("'src' must be a DOM element"); } }, /** @id MochiKit.Signal.disconnect */ disconnect: function (ident) { var self = MochiKit.Signal; var observers = self._observers; var m = MochiKit.Base; if (arguments.length > 1) { // compatibility API var src = MochiKit.DOM.getElement(arguments[0]); var sig = arguments[1]; var obj = arguments[2]; var func = arguments[3]; for (var i = observers.length - 1; i >= 0; i--) { var o = observers[i]; if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) { self._disconnect(o); if (!self._lock) { observers.splice(i, 1); } else { self._dirty = true; } return true; } } } else { var idx = m.findIdentical(observers, ident); if (idx >= 0) { self._disconnect(ident); if (!self._lock) { observers.splice(idx, 1); } else { self._dirty = true; } return true; } } return false; }, /** @id MochiKit.Signal.disconnectAllTo */ disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) { var self = MochiKit.Signal; var observers = self._observers; var disconnect = self._disconnect; var locked = self._lock; var dirty = self._dirty; if (typeof(funcOrStr) === 'undefined') { funcOrStr = null; } for (var i = observers.length - 1; i >= 0; i--) { var ident = observers[i]; if (ident.objOrFunc === objOrFunc && (funcOrStr === null || ident.funcOrStr === funcOrStr)) { disconnect(ident); if (locked) { dirty = true; } else { observers.splice(i, 1); } } } self._dirty = dirty; }, /** @id MochiKit.Signal.disconnectAll */ disconnectAll: function (src/* optional */, sig) { src = MochiKit.DOM.getElement(src); var m = MochiKit.Base; var signals = m.flattenArguments(m.extend(null, arguments, 1)); var self = MochiKit.Signal; var disconnect = self._disconnect; var observers = self._observers; var i, ident; var locked = self._lock; var dirty = self._dirty; if (signals.length === 0) { // disconnect all for (i = observers.length - 1; i >= 0; i--) { ident = observers[i]; if (ident.source === src) { disconnect(ident); if (!locked) { observers.splice(i, 1); } else { dirty = true; } } } } else { var sigs = {}; for (i = 0; i < signals.length; i++) { sigs[signals[i]] = true; } for (i = observers.length - 1; i >= 0; i--) { ident = observers[i]; if (ident.source === src && ident.signal in sigs) { disconnect(ident); if (!locked) { observers.splice(i, 1); } else { dirty = true; } } } } self._dirty = dirty; }, /** @id MochiKit.Signal.signal */ signal: function (src, sig) { var self = MochiKit.Signal; var observers = self._observers; src = MochiKit.DOM.getElement(src); var args = MochiKit.Base.extend(null, arguments, 2); var errors = []; self._lock = true; for (var i = 0; i < observers.length; i++) { var ident = observers[i]; if (ident.source === src && ident.signal === sig && ident.connected) { try { ident.listener.apply(src, args); } catch (e) { errors.push(e); } } } self._lock = false; if (self._dirty) { self._dirty = false; for (var i = observers.length - 1; i >= 0; i--) { if (!observers[i].connected) { observers.splice(i, 1); } } } if (errors.length == 1) { throw errors[0]; } else if (errors.length > 1) { var e = new Error("Multiple errors thrown in handling 'sig', see errors property"); e.errors = errors; throw e; } } }); MochiKit.Signal.EXPORT_OK = []; MochiKit.Signal.EXPORT = [ 'connect', 'disconnect', 'signal', 'disconnectAll', 'disconnectAllTo' ]; MochiKit.Signal.__new__ = function (win) { var m = MochiKit.Base; this._document = document; this._window = win; this._lock = false; this._dirty = false; try { this.connect(window, 'onunload', this._unloadCache); } catch (e) { // pass: might not be a browser } this.EXPORT_TAGS = { ':common': this.EXPORT, ':all': m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); }; MochiKit.Signal.__new__(this); // // XXX: Internet Explorer blows // if (MochiKit.__export__) { connect = MochiKit.Signal.connect; disconnect = MochiKit.Signal.disconnect; disconnectAll = MochiKit.Signal.disconnectAll; signal = MochiKit.Signal.signal; } MochiKit.Base._exportSymbols(this, MochiKit.Signal); MochiKit-1.4.2/lib/MochiKit/Async.js0000660000175000017500000004666511110670170016200 0ustar scottscott/*** MochiKit.Async 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('Async', ['Base']); MochiKit.Async.NAME = "MochiKit.Async"; MochiKit.Async.VERSION = "1.4.2"; MochiKit.Async.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.Async.toString = function () { return this.__repr__(); }; /** @id MochiKit.Async.Deferred */ MochiKit.Async.Deferred = function (/* optional */ canceller) { this.chain = []; this.id = this._nextId(); this.fired = -1; this.paused = 0; this.results = [null, null]; this.canceller = canceller; this.silentlyCancelled = false; this.chained = false; }; MochiKit.Async.Deferred.prototype = { /** @id MochiKit.Async.Deferred.prototype.repr */ repr: function () { var state; if (this.fired == -1) { state = 'unfired'; } else if (this.fired === 0) { state = 'success'; } else { state = 'error'; } return 'Deferred(' + this.id + ', ' + state + ')'; }, toString: MochiKit.Base.forwardCall("repr"), _nextId: MochiKit.Base.counter(), /** @id MochiKit.Async.Deferred.prototype.cancel */ cancel: function () { var self = MochiKit.Async; if (this.fired == -1) { if (this.canceller) { this.canceller(this); } else { this.silentlyCancelled = true; } if (this.fired == -1) { this.errback(new self.CancelledError(this)); } } else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) { this.results[0].cancel(); } }, _resback: function (res) { /*** The primitive that means either callback or errback ***/ this.fired = ((res instanceof Error) ? 1 : 0); this.results[this.fired] = res; this._fire(); }, _check: function () { if (this.fired != -1) { if (!this.silentlyCancelled) { throw new MochiKit.Async.AlreadyCalledError(this); } this.silentlyCancelled = false; return; } }, /** @id MochiKit.Async.Deferred.prototype.callback */ callback: function (res) { this._check(); if (res instanceof MochiKit.Async.Deferred) { throw new Error("Deferred instances can only be chained if they are the result of a callback"); } this._resback(res); }, /** @id MochiKit.Async.Deferred.prototype.errback */ errback: function (res) { this._check(); var self = MochiKit.Async; if (res instanceof self.Deferred) { throw new Error("Deferred instances can only be chained if they are the result of a callback"); } if (!(res instanceof Error)) { res = new self.GenericError(res); } this._resback(res); }, /** @id MochiKit.Async.Deferred.prototype.addBoth */ addBoth: function (fn) { if (arguments.length > 1) { fn = MochiKit.Base.partial.apply(null, arguments); } return this.addCallbacks(fn, fn); }, /** @id MochiKit.Async.Deferred.prototype.addCallback */ addCallback: function (fn) { if (arguments.length > 1) { fn = MochiKit.Base.partial.apply(null, arguments); } return this.addCallbacks(fn, null); }, /** @id MochiKit.Async.Deferred.prototype.addErrback */ addErrback: function (fn) { if (arguments.length > 1) { fn = MochiKit.Base.partial.apply(null, arguments); } return this.addCallbacks(null, fn); }, /** @id MochiKit.Async.Deferred.prototype.addCallbacks */ addCallbacks: function (cb, eb) { if (this.chained) { throw new Error("Chained Deferreds can not be re-used"); } this.chain.push([cb, eb]); if (this.fired >= 0) { this._fire(); } return this; }, _fire: function () { /*** Used internally to exhaust the callback sequence when a result is available. ***/ var chain = this.chain; var fired = this.fired; var res = this.results[fired]; var self = this; var cb = null; while (chain.length > 0 && this.paused === 0) { // Array var pair = chain.shift(); var f = pair[fired]; if (f === null) { continue; } try { res = f(res); fired = ((res instanceof Error) ? 1 : 0); if (res instanceof MochiKit.Async.Deferred) { cb = function (res) { self._resback(res); self.paused--; if ((self.paused === 0) && (self.fired >= 0)) { self._fire(); } }; this.paused++; } } catch (err) { fired = 1; if (!(err instanceof Error)) { err = new MochiKit.Async.GenericError(err); } res = err; } } this.fired = fired; this.results[fired] = res; if (cb && this.paused) { // this is for "tail recursion" in case the dependent deferred // is already fired res.addBoth(cb); res.chained = true; } } }; MochiKit.Base.update(MochiKit.Async, { /** @id MochiKit.Async.evalJSONRequest */ evalJSONRequest: function (req) { return MochiKit.Base.evalJSON(req.responseText); }, /** @id MochiKit.Async.succeed */ succeed: function (/* optional */result) { var d = new MochiKit.Async.Deferred(); d.callback.apply(d, arguments); return d; }, /** @id MochiKit.Async.fail */ fail: function (/* optional */result) { var d = new MochiKit.Async.Deferred(); d.errback.apply(d, arguments); return d; }, /** @id MochiKit.Async.getXMLHttpRequest */ getXMLHttpRequest: function () { var self = arguments.callee; if (!self.XMLHttpRequest) { var tryThese = [ function () { return new XMLHttpRequest(); }, function () { return new ActiveXObject('Msxml2.XMLHTTP'); }, function () { return new ActiveXObject('Microsoft.XMLHTTP'); }, function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); }, function () { throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest"); } ]; for (var i = 0; i < tryThese.length; i++) { var func = tryThese[i]; try { self.XMLHttpRequest = func; return func(); } catch (e) { // pass } } } return self.XMLHttpRequest(); }, _xhr_onreadystatechange: function (d) { // MochiKit.Logging.logDebug('this.readyState', this.readyState); var m = MochiKit.Base; if (this.readyState == 4) { // IE SUCKS try { this.onreadystatechange = null; } catch (e) { try { this.onreadystatechange = m.noop; } catch (e) { } } var status = null; try { status = this.status; if (!status && m.isNotEmpty(this.responseText)) { // 0 or undefined seems to mean cached or local status = 304; } } catch (e) { // pass // MochiKit.Logging.logDebug('error getting status?', repr(items(e))); } // 200 is OK, 201 is CREATED, 204 is NO CONTENT // 304 is NOT MODIFIED, 1223 is apparently a bug in IE if (status == 200 || status == 201 || status == 204 || status == 304 || status == 1223) { d.callback(this); } else { var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed"); if (err.number) { // XXX: This seems to happen on page change d.errback(err); } else { // XXX: this seems to happen when the server is unreachable d.errback(err); } } } }, _xhr_canceller: function (req) { // IE SUCKS try { req.onreadystatechange = null; } catch (e) { try { req.onreadystatechange = MochiKit.Base.noop; } catch (e) { } } req.abort(); }, /** @id MochiKit.Async.sendXMLHttpRequest */ sendXMLHttpRequest: function (req, /* optional */ sendContent) { if (typeof(sendContent) == "undefined" || sendContent === null) { sendContent = ""; } var m = MochiKit.Base; var self = MochiKit.Async; var d = new self.Deferred(m.partial(self._xhr_canceller, req)); try { req.onreadystatechange = m.bind(self._xhr_onreadystatechange, req, d); req.send(sendContent); } catch (e) { try { req.onreadystatechange = null; } catch (ignore) { // pass } d.errback(e); } return d; }, /** @id MochiKit.Async.doXHR */ doXHR: function (url, opts) { /* Work around a Firefox bug by dealing with XHR during the next event loop iteration. Maybe it's this one: https://bugzilla.mozilla.org/show_bug.cgi?id=249843 */ var self = MochiKit.Async; return self.callLater(0, self._doXHR, url, opts); }, _doXHR: function (url, opts) { var m = MochiKit.Base; opts = m.update({ method: 'GET', sendContent: '' /* queryString: undefined, username: undefined, password: undefined, headers: undefined, mimeType: undefined */ }, opts); var self = MochiKit.Async; var req = self.getXMLHttpRequest(); if (opts.queryString) { var qs = m.queryString(opts.queryString); if (qs) { url += "?" + qs; } } // Safari will send undefined:undefined, so we have to check. // We can't use apply, since the function is native. if ('username' in opts) { req.open(opts.method, url, true, opts.username, opts.password); } else { req.open(opts.method, url, true); } if (req.overrideMimeType && opts.mimeType) { req.overrideMimeType(opts.mimeType); } req.setRequestHeader("X-Requested-With", "XMLHttpRequest"); if (opts.headers) { var headers = opts.headers; if (!m.isArrayLike(headers)) { headers = m.items(headers); } for (var i = 0; i < headers.length; i++) { var header = headers[i]; var name = header[0]; var value = header[1]; req.setRequestHeader(name, value); } } return self.sendXMLHttpRequest(req, opts.sendContent); }, _buildURL: function (url/*, ...*/) { if (arguments.length > 1) { var m = MochiKit.Base; var qs = m.queryString.apply(null, m.extend(null, arguments, 1)); if (qs) { return url + "?" + qs; } } return url; }, /** @id MochiKit.Async.doSimpleXMLHttpRequest */ doSimpleXMLHttpRequest: function (url/*, ...*/) { var self = MochiKit.Async; url = self._buildURL.apply(self, arguments); return self.doXHR(url); }, /** @id MochiKit.Async.loadJSONDoc */ loadJSONDoc: function (url/*, ...*/) { var self = MochiKit.Async; url = self._buildURL.apply(self, arguments); var d = self.doXHR(url, { 'mimeType': 'text/plain', 'headers': [['Accept', 'application/json']] }); d = d.addCallback(self.evalJSONRequest); return d; }, /** @id MochiKit.Async.wait */ wait: function (seconds, /* optional */value) { var d = new MochiKit.Async.Deferred(); var m = MochiKit.Base; if (typeof(value) != 'undefined') { d.addCallback(function () { return value; }); } var timeout = setTimeout( m.bind("callback", d), Math.floor(seconds * 1000)); d.canceller = function () { try { clearTimeout(timeout); } catch (e) { // pass } }; return d; }, /** @id MochiKit.Async.callLater */ callLater: function (seconds, func) { var m = MochiKit.Base; var pfunc = m.partial.apply(m, m.extend(null, arguments, 1)); return MochiKit.Async.wait(seconds).addCallback( function (res) { return pfunc(); } ); } }); /** @id MochiKit.Async.DeferredLock */ MochiKit.Async.DeferredLock = function () { this.waiting = []; this.locked = false; this.id = this._nextId(); }; MochiKit.Async.DeferredLock.prototype = { __class__: MochiKit.Async.DeferredLock, /** @id MochiKit.Async.DeferredLock.prototype.acquire */ acquire: function () { var d = new MochiKit.Async.Deferred(); if (this.locked) { this.waiting.push(d); } else { this.locked = true; d.callback(this); } return d; }, /** @id MochiKit.Async.DeferredLock.prototype.release */ release: function () { if (!this.locked) { throw TypeError("Tried to release an unlocked DeferredLock"); } this.locked = false; if (this.waiting.length > 0) { this.locked = true; this.waiting.shift().callback(this); } }, _nextId: MochiKit.Base.counter(), repr: function () { var state; if (this.locked) { state = 'locked, ' + this.waiting.length + ' waiting'; } else { state = 'unlocked'; } return 'DeferredLock(' + this.id + ', ' + state + ')'; }, toString: MochiKit.Base.forwardCall("repr") }; /** @id MochiKit.Async.DeferredList */ MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) { // call parent constructor MochiKit.Async.Deferred.apply(this, [canceller]); this.list = list; var resultList = []; this.resultList = resultList; this.finishedCount = 0; this.fireOnOneCallback = fireOnOneCallback; this.fireOnOneErrback = fireOnOneErrback; this.consumeErrors = consumeErrors; var cb = MochiKit.Base.bind(this._cbDeferred, this); for (var i = 0; i < list.length; i++) { var d = list[i]; resultList.push(undefined); d.addCallback(cb, i, true); d.addErrback(cb, i, false); } if (list.length === 0 && !fireOnOneCallback) { this.callback(this.resultList); } }; MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred(); MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) { this.resultList[index] = [succeeded, result]; this.finishedCount += 1; if (this.fired == -1) { if (succeeded && this.fireOnOneCallback) { this.callback([index, result]); } else if (!succeeded && this.fireOnOneErrback) { this.errback(result); } else if (this.finishedCount == this.list.length) { this.callback(this.resultList); } } if (!succeeded && this.consumeErrors) { result = null; } return result; }; /** @id MochiKit.Async.gatherResults */ MochiKit.Async.gatherResults = function (deferredList) { var d = new MochiKit.Async.DeferredList(deferredList, false, true, false); d.addCallback(function (results) { var ret = []; for (var i = 0; i < results.length; i++) { ret.push(results[i][1]); } return ret; }); return d; }; /** @id MochiKit.Async.maybeDeferred */ MochiKit.Async.maybeDeferred = function (func) { var self = MochiKit.Async; var result; try { var r = func.apply(null, MochiKit.Base.extend([], arguments, 1)); if (r instanceof self.Deferred) { result = r; } else if (r instanceof Error) { result = self.fail(r); } else { result = self.succeed(r); } } catch (e) { result = self.fail(e); } return result; }; MochiKit.Async.EXPORT = [ "AlreadyCalledError", "CancelledError", "BrowserComplianceError", "GenericError", "XMLHttpRequestError", "Deferred", "succeed", "fail", "getXMLHttpRequest", "doSimpleXMLHttpRequest", "loadJSONDoc", "wait", "callLater", "sendXMLHttpRequest", "DeferredLock", "DeferredList", "gatherResults", "maybeDeferred", "doXHR" ]; MochiKit.Async.EXPORT_OK = [ "evalJSONRequest" ]; MochiKit.Async.__new__ = function () { var m = MochiKit.Base; var ne = m.partial(m._newNamedError, this); ne("AlreadyCalledError", /** @id MochiKit.Async.AlreadyCalledError */ function (deferred) { /*** Raised by the Deferred if callback or errback happens after it was already fired. ***/ this.deferred = deferred; } ); ne("CancelledError", /** @id MochiKit.Async.CancelledError */ function (deferred) { /*** Raised by the Deferred cancellation mechanism. ***/ this.deferred = deferred; } ); ne("BrowserComplianceError", /** @id MochiKit.Async.BrowserComplianceError */ function (msg) { /*** Raised when the JavaScript runtime is not capable of performing the given function. Technically, this should really never be raised because a non-conforming JavaScript runtime probably isn't going to support exceptions in the first place. ***/ this.message = msg; } ); ne("GenericError", /** @id MochiKit.Async.GenericError */ function (msg) { this.message = msg; } ); ne("XMLHttpRequestError", /** @id MochiKit.Async.XMLHttpRequestError */ function (req, msg) { /*** Raised when an XMLHttpRequest does not complete for any reason. ***/ this.req = req; this.message = msg; try { // Strange but true that this can raise in some cases. this.number = req.status; } catch (e) { // pass } } ); this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); }; MochiKit.Async.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.Async); MochiKit-1.4.2/lib/MochiKit/Logging.js0000660000175000017500000002224211110670074016475 0ustar scottscott/*** MochiKit.Logging 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ MochiKit.Base._deps('Logging', ['Base']); MochiKit.Logging.NAME = "MochiKit.Logging"; MochiKit.Logging.VERSION = "1.4.2"; MochiKit.Logging.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.Logging.toString = function () { return this.__repr__(); }; MochiKit.Logging.EXPORT = [ "LogLevel", "LogMessage", "Logger", "alertListener", "logger", "log", "logError", "logDebug", "logFatal", "logWarning" ]; MochiKit.Logging.EXPORT_OK = [ "logLevelAtLeast", "isLogMessage", "compareLogMessage" ]; /** @id MochiKit.Logging.LogMessage */ MochiKit.Logging.LogMessage = function (num, level, info) { this.num = num; this.level = level; this.info = info; this.timestamp = new Date(); }; MochiKit.Logging.LogMessage.prototype = { /** @id MochiKit.Logging.LogMessage.prototype.repr */ repr: function () { var m = MochiKit.Base; return 'LogMessage(' + m.map( m.repr, [this.num, this.level, this.info] ).join(', ') + ')'; }, /** @id MochiKit.Logging.LogMessage.prototype.toString */ toString: MochiKit.Base.forwardCall("repr") }; MochiKit.Base.update(MochiKit.Logging, { /** @id MochiKit.Logging.logLevelAtLeast */ logLevelAtLeast: function (minLevel) { var self = MochiKit.Logging; if (typeof(minLevel) == 'string') { minLevel = self.LogLevel[minLevel]; } return function (msg) { var msgLevel = msg.level; if (typeof(msgLevel) == 'string') { msgLevel = self.LogLevel[msgLevel]; } return msgLevel >= minLevel; }; }, /** @id MochiKit.Logging.isLogMessage */ isLogMessage: function (/* ... */) { var LogMessage = MochiKit.Logging.LogMessage; for (var i = 0; i < arguments.length; i++) { if (!(arguments[i] instanceof LogMessage)) { return false; } } return true; }, /** @id MochiKit.Logging.compareLogMessage */ compareLogMessage: function (a, b) { return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]); }, /** @id MochiKit.Logging.alertListener */ alertListener: function (msg) { alert( "num: " + msg.num + "\nlevel: " + msg.level + "\ninfo: " + msg.info.join(" ") ); } }); /** @id MochiKit.Logging.Logger */ MochiKit.Logging.Logger = function (/* optional */maxSize) { this.counter = 0; if (typeof(maxSize) == 'undefined' || maxSize === null) { maxSize = -1; } this.maxSize = maxSize; this._messages = []; this.listeners = {}; this.useNativeConsole = false; }; MochiKit.Logging.Logger.prototype = { /** @id MochiKit.Logging.Logger.prototype.clear */ clear: function () { this._messages.splice(0, this._messages.length); }, /** @id MochiKit.Logging.Logger.prototype.logToConsole */ logToConsole: function (msg) { if (typeof(window) != "undefined" && window.console && window.console.log) { // Safari and FireBug 0.4 // Percent replacement is a workaround for cute Safari crashing bug window.console.log(msg.replace(/%/g, '\uFF05')); } else if (typeof(opera) != "undefined" && opera.postError) { // Opera opera.postError(msg); } else if (typeof(printfire) == "function") { // FireBug 0.3 and earlier printfire(msg); } else if (typeof(Debug) != "undefined" && Debug.writeln) { // IE Web Development Helper (?) // http://www.nikhilk.net/Entry.aspx?id=93 Debug.writeln(msg); } else if (typeof(debug) != "undefined" && debug.trace) { // Atlas framework (?) // http://www.nikhilk.net/Entry.aspx?id=93 debug.trace(msg); } }, /** @id MochiKit.Logging.Logger.prototype.dispatchListeners */ dispatchListeners: function (msg) { for (var k in this.listeners) { var pair = this.listeners[k]; if (pair.ident != k || (pair[0] && !pair[0](msg))) { continue; } pair[1](msg); } }, /** @id MochiKit.Logging.Logger.prototype.addListener */ addListener: function (ident, filter, listener) { if (typeof(filter) == 'string') { filter = MochiKit.Logging.logLevelAtLeast(filter); } var entry = [filter, listener]; entry.ident = ident; this.listeners[ident] = entry; }, /** @id MochiKit.Logging.Logger.prototype.removeListener */ removeListener: function (ident) { delete this.listeners[ident]; }, /** @id MochiKit.Logging.Logger.prototype.baseLog */ baseLog: function (level, message/*, ...*/) { if (typeof(level) == "number") { if (level >= MochiKit.Logging.LogLevel.FATAL) { level = 'FATAL'; } else if (level >= MochiKit.Logging.LogLevel.ERROR) { level = 'ERROR'; } else if (level >= MochiKit.Logging.LogLevel.WARNING) { level = 'WARNING'; } else if (level >= MochiKit.Logging.LogLevel.INFO) { level = 'INFO'; } else { level = 'DEBUG'; } } var msg = new MochiKit.Logging.LogMessage( this.counter, level, MochiKit.Base.extend(null, arguments, 1) ); this._messages.push(msg); this.dispatchListeners(msg); if (this.useNativeConsole) { this.logToConsole(msg.level + ": " + msg.info.join(" ")); } this.counter += 1; while (this.maxSize >= 0 && this._messages.length > this.maxSize) { this._messages.shift(); } }, /** @id MochiKit.Logging.Logger.prototype.getMessages */ getMessages: function (howMany) { var firstMsg = 0; if (!(typeof(howMany) == 'undefined' || howMany === null)) { firstMsg = Math.max(0, this._messages.length - howMany); } return this._messages.slice(firstMsg); }, /** @id MochiKit.Logging.Logger.prototype.getMessageText */ getMessageText: function (howMany) { if (typeof(howMany) == 'undefined' || howMany === null) { howMany = 30; } var messages = this.getMessages(howMany); if (messages.length) { var lst = map(function (m) { return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' '); }, messages); lst.unshift('LAST ' + messages.length + ' MESSAGES:'); return lst.join(''); } return ''; }, /** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */ debuggingBookmarklet: function (inline) { if (typeof(MochiKit.LoggingPane) == "undefined") { alert(this.getMessageText()); } else { MochiKit.LoggingPane.createLoggingPane(inline || false); } } }; MochiKit.Logging.__new__ = function () { this.LogLevel = { ERROR: 40, FATAL: 50, WARNING: 30, INFO: 20, DEBUG: 10 }; var m = MochiKit.Base; m.registerComparator("LogMessage", this.isLogMessage, this.compareLogMessage ); var partial = m.partial; var Logger = this.Logger; var baseLog = Logger.prototype.baseLog; m.update(this.Logger.prototype, { debug: partial(baseLog, 'DEBUG'), log: partial(baseLog, 'INFO'), error: partial(baseLog, 'ERROR'), fatal: partial(baseLog, 'FATAL'), warning: partial(baseLog, 'WARNING') }); // indirectly find logger so it can be replaced var self = this; var connectLog = function (name) { return function () { self.logger[name].apply(self.logger, arguments); }; }; /** @id MochiKit.Logging.log */ this.log = connectLog('log'); /** @id MochiKit.Logging.logError */ this.logError = connectLog('error'); /** @id MochiKit.Logging.logDebug */ this.logDebug = connectLog('debug'); /** @id MochiKit.Logging.logFatal */ this.logFatal = connectLog('fatal'); /** @id MochiKit.Logging.logWarning */ this.logWarning = connectLog('warning'); this.logger = new Logger(); this.logger.useNativeConsole = true; this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": m.concat(this.EXPORT, this.EXPORT_OK) }; m.nameFunctions(this); }; if (typeof(printfire) == "undefined" && typeof(document) != "undefined" && document.createEvent && typeof(dispatchEvent) != "undefined") { // FireBug really should be less lame about this global function printfire = function () { printfire.args = arguments; var ev = document.createEvent("Events"); ev.initEvent("printfire", false, true); dispatchEvent(ev); }; } MochiKit.Logging.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.Logging); MochiKit-1.4.2/lib/MochiKit/MochiKit.js0000660000175000017500000001342311110670054016615 0ustar scottscott/*** MochiKit.MochiKit 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito. All rights Reserved. ***/ if (typeof(MochiKit) == 'undefined') { MochiKit = {}; } if (typeof(MochiKit.MochiKit) == 'undefined') { /** @id MochiKit.MochiKit */ MochiKit.MochiKit = {}; } MochiKit.MochiKit.NAME = "MochiKit.MochiKit"; MochiKit.MochiKit.VERSION = "1.4.2"; MochiKit.MochiKit.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; /** @id MochiKit.MochiKit.toString */ MochiKit.MochiKit.toString = function () { return this.__repr__(); }; /** @id MochiKit.MochiKit.SUBMODULES */ MochiKit.MochiKit.SUBMODULES = [ "Base", "Iter", "Logging", "DateTime", "Format", "Async", "DOM", "Selector", "Style", "LoggingPane", "Color", "Signal", "Position", "Visual", "DragAndDrop", "Sortable" ]; if (typeof(JSAN) != 'undefined' || typeof(dojo) != 'undefined') { if (typeof(dojo) != 'undefined') { dojo.provide('MochiKit.MochiKit'); (function (lst) { for (var i = 0; i < lst.length; i++) { dojo.require("MochiKit." + lst[i]); } })(MochiKit.MochiKit.SUBMODULES); } if (typeof(JSAN) != 'undefined') { (function (lst) { for (var i = 0; i < lst.length; i++) { JSAN.use("MochiKit." + lst[i], []); } })(MochiKit.MochiKit.SUBMODULES); } (function () { var extend = MochiKit.Base.extend; var self = MochiKit.MochiKit; var modules = self.SUBMODULES; var EXPORT = []; var EXPORT_OK = []; var EXPORT_TAGS = {}; var i, k, m, all; for (i = 0; i < modules.length; i++) { m = MochiKit[modules[i]]; extend(EXPORT, m.EXPORT); extend(EXPORT_OK, m.EXPORT_OK); for (k in m.EXPORT_TAGS) { EXPORT_TAGS[k] = extend(EXPORT_TAGS[k], m.EXPORT_TAGS[k]); } all = m.EXPORT_TAGS[":all"]; if (!all) { all = extend(null, m.EXPORT, m.EXPORT_OK); } var j; for (j = 0; j < all.length; j++) { k = all[j]; self[k] = m[k]; } } self.EXPORT = EXPORT; self.EXPORT_OK = EXPORT_OK; self.EXPORT_TAGS = EXPORT_TAGS; }()); } else { if (typeof(MochiKit.__compat__) == 'undefined') { MochiKit.__compat__ = true; } (function () { if (typeof(document) == "undefined") { return; } var scripts = document.getElementsByTagName("script"); var kXHTMLNSURI = "http://www.w3.org/1999/xhtml"; var kSVGNSURI = "http://www.w3.org/2000/svg"; var kXLINKNSURI = "http://www.w3.org/1999/xlink"; var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var base = null; var baseElem = null; var allScripts = {}; var i; var src; for (i = 0; i < scripts.length; i++) { src = null; switch (scripts[i].namespaceURI) { case kSVGNSURI: src = scripts[i].getAttributeNS(kXLINKNSURI, "href"); break; /* case null: // HTML case '': // HTML case kXHTMLNSURI: case kXULNSURI: */ default: src = scripts[i].getAttribute("src"); break; } if (!src) { continue; } allScripts[src] = true; if (src.match(/MochiKit.js(\?.*)?$/)) { base = src.substring(0, src.lastIndexOf('MochiKit.js')); baseElem = scripts[i]; } } if (base === null) { return; } var modules = MochiKit.MochiKit.SUBMODULES; for (var i = 0; i < modules.length; i++) { if (MochiKit[modules[i]]) { continue; } var uri = base + modules[i] + '.js'; if (uri in allScripts) { continue; } if (baseElem.namespaceURI == kSVGNSURI || baseElem.namespaceURI == kXULNSURI) { // SVG, XUL /* SVG does not support document.write, so if Safari wants to support SVG tests it should fix its deferred loading bug (see following below). */ var s = document.createElementNS(baseElem.namespaceURI, 'script'); s.setAttribute("id", "MochiKit_" + base + modules[i]); if (baseElem.namespaceURI == kSVGNSURI) { s.setAttributeNS(kXLINKNSURI, 'href', uri); } else { s.setAttribute('src', uri); } s.setAttribute("type", "application/x-javascript"); baseElem.parentNode.appendChild(s); } else { // HTML, XHTML /* DOM can not be used here because Safari does deferred loading of scripts unless they are in the document or inserted with document.write This is not XHTML compliant. If you want XHTML compliance then you must use the packed version of MochiKit or include each script individually (basically unroll these document.write calls into your XHTML source) */ document.write('<' + baseElem.nodeName + ' src="' + uri + '" type="text/javascript">'); } }; })(); } MochiKit-1.4.2/lib/MochiKit/Color.js0000660000175000017500000006036011110670150016163 0ustar scottscott/*** MochiKit.Color 1.4.2 See for documentation, downloads, license, etc. (c) 2005 Bob Ippolito and others. All rights Reserved. ***/ MochiKit.Base._deps('Color', ['Base', 'DOM', 'Style']); MochiKit.Color.NAME = "MochiKit.Color"; MochiKit.Color.VERSION = "1.4.2"; MochiKit.Color.__repr__ = function () { return "[" + this.NAME + " " + this.VERSION + "]"; }; MochiKit.Color.toString = function () { return this.__repr__(); }; /** @id MochiKit.Color.Color */ MochiKit.Color.Color = function (red, green, blue, alpha) { if (typeof(alpha) == 'undefined' || alpha === null) { alpha = 1.0; } this.rgb = { r: red, g: green, b: blue, a: alpha }; }; // Prototype methods MochiKit.Color.Color.prototype = { __class__: MochiKit.Color.Color, /** @id MochiKit.Color.Color.prototype.colorWithAlpha */ colorWithAlpha: function (alpha) { var rgb = this.rgb; var m = MochiKit.Color; return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha); }, /** @id MochiKit.Color.Color.prototype.colorWithHue */ colorWithHue: function (hue) { // get an HSL model, and set the new hue... var hsl = this.asHSL(); hsl.h = hue; var m = MochiKit.Color; // convert back to RGB... return m.Color.fromHSL(hsl); }, /** @id MochiKit.Color.Color.prototype.colorWithSaturation */ colorWithSaturation: function (saturation) { // get an HSL model, and set the new hue... var hsl = this.asHSL(); hsl.s = saturation; var m = MochiKit.Color; // convert back to RGB... return m.Color.fromHSL(hsl); }, /** @id MochiKit.Color.Color.prototype.colorWithLightness */ colorWithLightness: function (lightness) { // get an HSL model, and set the new hue... var hsl = this.asHSL(); hsl.l = lightness; var m = MochiKit.Color; // convert back to RGB... return m.Color.fromHSL(hsl); }, /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */ darkerColorWithLevel: function (level) { var hsl = this.asHSL(); hsl.l = Math.max(hsl.l - level, 0); var m = MochiKit.Color; return m.Color.fromHSL(hsl); }, /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */ lighterColorWithLevel: function (level) { var hsl = this.asHSL(); hsl.l = Math.min(hsl.l + level, 1); var m = MochiKit.Color; return m.Color.fromHSL(hsl); }, /** @id MochiKit.Color.Color.prototype.blendedColor */ blendedColor: function (other, /* optional */ fraction) { if (typeof(fraction) == 'undefined' || fraction === null) { fraction = 0.5; } var sf = 1.0 - fraction; var s = this.rgb; var d = other.rgb; var df = fraction; return MochiKit.Color.Color.fromRGB( (s.r * sf) + (d.r * df), (s.g * sf) + (d.g * df), (s.b * sf) + (d.b * df), (s.a * sf) + (d.a * df) ); }, /** @id MochiKit.Color.Color.prototype.compareRGB */ compareRGB: function (other) { var a = this.asRGB(); var b = other.asRGB(); return MochiKit.Base.compare( [a.r, a.g, a.b, a.a], [b.r, b.g, b.b, b.a] ); }, /** @id MochiKit.Color.Color.prototype.isLight */ isLight: function () { return this.asHSL().b > 0.5; }, /** @id MochiKit.Color.Color.prototype.isDark */ isDark: function () { return (!this.isLight()); }, /** @id MochiKit.Color.Color.prototype.toHSLString */ toHSLString: function () { var c = this.asHSL(); var ccc = MochiKit.Color.clampColorComponent; var rval = this._hslString; if (!rval) { var mid = ( ccc(c.h, 360).toFixed(0) + "," + ccc(c.s, 100).toPrecision(4) + "%" + "," + ccc(c.l, 100).toPrecision(4) + "%" ); var a = c.a; if (a >= 1) { a = 1; rval = "hsl(" + mid + ")"; } else { if (a <= 0) { a = 0; } rval = "hsla(" + mid + "," + a + ")"; } this._hslString = rval; } return rval; }, /** @id MochiKit.Color.Color.prototype.toRGBString */ toRGBString: function () { var c = this.rgb; var ccc = MochiKit.Color.clampColorComponent; var rval = this._rgbString; if (!rval) { var mid = ( ccc(c.r, 255).toFixed(0) + "," + ccc(c.g, 255).toFixed(0) + "," + ccc(c.b, 255).toFixed(0) ); if (c.a != 1) { rval = "rgba(" + mid + "," + c.a + ")"; } else { rval = "rgb(" + mid + ")"; } this._rgbString = rval; } return rval; }, /** @id MochiKit.Color.Color.prototype.asRGB */ asRGB: function () { return MochiKit.Base.clone(this.rgb); }, /** @id MochiKit.Color.Color.prototype.toHexString */ toHexString: function () { var m = MochiKit.Color; var c = this.rgb; var ccc = MochiKit.Color.clampColorComponent; var rval = this._hexString; if (!rval) { rval = ("#" + m.toColorPart(ccc(c.r, 255)) + m.toColorPart(ccc(c.g, 255)) + m.toColorPart(ccc(c.b, 255)) ); this._hexString = rval; } return rval; }, /** @id MochiKit.Color.Color.prototype.asHSV */ asHSV: function () { var hsv = this.hsv; var c = this.rgb; if (typeof(hsv) == 'undefined' || hsv === null) { hsv = MochiKit.Color.rgbToHSV(this.rgb); this.hsv = hsv; } return MochiKit.Base.clone(hsv); }, /** @id MochiKit.Color.Color.prototype.asHSL */ asHSL: function () { var hsl = this.hsl; var c = this.rgb; if (typeof(hsl) == 'undefined' || hsl === null) { hsl = MochiKit.Color.rgbToHSL(this.rgb); this.hsl = hsl; } return MochiKit.Base.clone(hsl); }, /** @id MochiKit.Color.Color.prototype.toString */ toString: function () { return this.toRGBString(); }, /** @id MochiKit.Color.Color.prototype.repr */ repr: function () { var c = this.rgb; var col = [c.r, c.g, c.b, c.a]; return this.__class__.NAME + "(" + col.join(", ") + ")"; } }; // Constructor methods MochiKit.Base.update(MochiKit.Color.Color, { /** @id MochiKit.Color.Color.fromRGB */ fromRGB: function (red, green, blue, alpha) { // designated initializer var Color = MochiKit.Color.Color; if (arguments.length == 1) { var rgb = red; red = rgb.r; green = rgb.g; blue = rgb.b; if (typeof(rgb.a) == 'undefined') { alpha = undefined; } else { alpha = rgb.a; } } return new Color(red, green, blue, alpha); }, /** @id MochiKit.Color.Color.fromHSL */ fromHSL: function (hue, saturation, lightness, alpha) { var m = MochiKit.Color; return m.Color.fromRGB(m.hslToRGB.apply(m, arguments)); }, /** @id MochiKit.Color.Color.fromHSV */ fromHSV: function (hue, saturation, value, alpha) { var m = MochiKit.Color; return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments)); }, /** @id MochiKit.Color.Color.fromName */ fromName: function (name) { var Color = MochiKit.Color.Color; // Opera 9 seems to "quote" named colors(?!) if (name.charAt(0) == '"') { name = name.substr(1, name.length - 2); } var htmlColor = Color._namedColors[name.toLowerCase()]; if (typeof(htmlColor) == 'string') { return Color.fromHexString(htmlColor); } else if (name == "transparent") { return Color.transparentColor(); } return null; }, /** @id MochiKit.Color.Color.fromString */ fromString: function (colorString) { var self = MochiKit.Color.Color; var three = colorString.substr(0, 3); if (three == "rgb") { return self.fromRGBString(colorString); } else if (three == "hsl") { return self.fromHSLString(colorString); } else if (colorString.charAt(0) == "#") { return self.fromHexString(colorString); } return self.fromName(colorString); }, /** @id MochiKit.Color.Color.fromHexString */ fromHexString: function (hexCode) { if (hexCode.charAt(0) == '#') { hexCode = hexCode.substring(1); } var components = []; var i, hex; if (hexCode.length == 3) { for (i = 0; i < 3; i++) { hex = hexCode.substr(i, 1); components.push(parseInt(hex + hex, 16) / 255.0); } } else { for (i = 0; i < 6; i += 2) { hex = hexCode.substr(i, 2); components.push(parseInt(hex, 16) / 255.0); } } var Color = MochiKit.Color.Color; return Color.fromRGB.apply(Color, components); }, _fromColorString: function (pre, method, scales, colorCode) { // parses either HSL or RGB if (colorCode.indexOf(pre) === 0) { colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1); } var colorChunks = colorCode.split(/\s*,\s*/); var colorFloats = []; for (var i = 0; i < colorChunks.length; i++) { var c = colorChunks[i]; var val; var three = c.substring(c.length - 3); if (c.charAt(c.length - 1) == '%') { val = 0.01 * parseFloat(c.substring(0, c.length - 1)); } else if (three == "deg") { val = parseFloat(c) / 360.0; } else if (three == "rad") { val = parseFloat(c) / (Math.PI * 2); } else { val = scales[i] * parseFloat(c); } colorFloats.push(val); } return this[method].apply(this, colorFloats); }, /** @id MochiKit.Color.Color.fromComputedStyle */ fromComputedStyle: function (elem, style) { var d = MochiKit.DOM; var cls = MochiKit.Color.Color; for (elem = d.getElement(elem); elem; elem = elem.parentNode) { var actualColor = MochiKit.Style.getStyle.apply(d, arguments); if (!actualColor) { continue; } var color = cls.fromString(actualColor); if (!color) { break; } if (color.asRGB().a > 0) { return color; } } return null; }, /** @id MochiKit.Color.Color.fromBackground */ fromBackground: function (elem) { var cls = MochiKit.Color.Color; return cls.fromComputedStyle( elem, "backgroundColor", "background-color") || cls.whiteColor(); }, /** @id MochiKit.Color.Color.fromText */ fromText: function (elem) { var cls = MochiKit.Color.Color; return cls.fromComputedStyle( elem, "color", "color") || cls.blackColor(); }, /** @id MochiKit.Color.Color.namedColors */ namedColors: function () { return MochiKit.Base.clone(MochiKit.Color.Color._namedColors); } }); // Module level functions MochiKit.Base.update(MochiKit.Color, { /** @id MochiKit.Color.clampColorComponent */ clampColorComponent: function (v, scale) { v *= scale; if (v < 0) { return 0; } else if (v > scale) { return scale; } else { return v; } }, _hslValue: function (n1, n2, hue) { if (hue > 6.0) { hue -= 6.0; } else if (hue < 0.0) { hue += 6.0; } var val; if (hue < 1.0) { val = n1 + (n2 - n1) * hue; } else if (hue < 3.0) { val = n2; } else if (hue < 4.0) { val = n1 + (n2 - n1) * (4.0 - hue); } else { val = n1; } return val; }, /** @id MochiKit.Color.hsvToRGB */ hsvToRGB: function (hue, saturation, value, alpha) { if (arguments.length == 1) { var hsv = hue; hue = hsv.h; saturation = hsv.s; value = hsv.v; alpha = hsv.a; } var red; var green; var blue; if (saturation === 0) { red = value; green = value; blue = value; } else { var i = Math.floor(hue * 6); var f = (hue * 6) - i; var p = value * (1 - saturation); var q = value * (1 - (saturation * f)); var t = value * (1 - (saturation * (1 - f))); switch (i) { case 1: red = q; green = value; blue = p; break; case 2: red = p; green = value; blue = t; break; case 3: red = p; green = q; blue = value; break; case 4: red = t; green = p; blue = value; break; case 5: red = value; green = p; blue = q; break; case 6: // fall through case 0: red = value; green = t; blue = p; break; } } return { r: red, g: green, b: blue, a: alpha }; }, /** @id MochiKit.Color.hslToRGB */ hslToRGB: function (hue, saturation, lightness, alpha) { if (arguments.length == 1) { var hsl = hue; hue = hsl.h; saturation = hsl.s; lightness = hsl.l; alpha = hsl.a; } var red; var green; var blue; if (saturation === 0) { red = lightness; green = lightness; blue = lightness; } else { var m2; if (lightness <= 0.5) { m2 = lightness * (1.0 + saturation); } else { m2 = lightness + saturation - (lightness * saturation); } var m1 = (2.0 * lightness) - m2; var f = MochiKit.Color._hslValue; var h6 = hue * 6.0; red = f(m1, m2, h6 + 2); green = f(m1, m2, h6); blue = f(m1, m2, h6 - 2); } return { r: red, g: green, b: blue, a: alpha }; }, /** @id MochiKit.Color.rgbToHSV */ rgbToHSV: function (red, green, blue, alpha) { if (arguments.length == 1) { var rgb = red; red = rgb.r; green = rgb.g; blue = rgb.b; alpha = rgb.a; } var max = Math.max(Math.max(red, green), blue); var min = Math.min(Math.min(red, green), blue); var hue; var saturation; var value = max; if (min == max) { hue = 0; saturation = 0; } else { var delta = (max - min); saturation = delta / max; if (red == max) { hue = (green - blue) / delta; } else if (green == max) { hue = 2 + ((blue - red) / delta); } else { hue = 4 + ((red - green) / delta); } hue /= 6; if (hue < 0) { hue += 1; } if (hue > 1) { hue -= 1; } } return { h: hue, s: saturation, v: value, a: alpha }; }, /** @id MochiKit.Color.rgbToHSL */ rgbToHSL: function (red, green, blue, alpha) { if (arguments.length == 1) { var rgb = red; red = rgb.r; green = rgb.g; blue = rgb.b; alpha = rgb.a; } var max = Math.max(red, Math.max(green, blue)); var min = Math.min(red, Math.min(green, blue)); var hue; var saturation; var lightness = (max + min) / 2.0; var delta = max - min; if (delta === 0) { hue = 0; saturation = 0; } else { if (lightness <= 0.5) { saturation = delta / (max + min); } else { saturation = delta / (2 - max - min); } if (red == max) { hue = (green - blue) / delta; } else if (green == max) { hue = 2 + ((blue - red) / delta); } else { hue = 4 + ((red - green) / delta); } hue /= 6; if (hue < 0) { hue += 1; } if (hue > 1) { hue -= 1; } } return { h: hue, s: saturation, l: lightness, a: alpha }; }, /** @id MochiKit.Color.toColorPart */ toColorPart: function (num) { num = Math.round(num); var digits = num.toString(16); if (num < 16) { return '0' + digits; } return digits; }, __new__: function () { var m = MochiKit.Base; /** @id MochiKit.Color.fromRGBString */ this.Color.fromRGBString = m.bind( this.Color._fromColorString, this.Color, "rgb", "fromRGB", [1.0/255.0, 1.0/255.0, 1.0/255.0, 1] ); /** @id MochiKit.Color.fromHSLString */ this.Color.fromHSLString = m.bind( this.Color._fromColorString, this.Color, "hsl", "fromHSL", [1.0/360.0, 0.01, 0.01, 1] ); var third = 1.0 / 3.0; /** @id MochiKit.Color.colors */ var colors = { // NSColor colors plus transparent /** @id MochiKit.Color.blackColor */ black: [0, 0, 0], /** @id MochiKit.Color.blueColor */ blue: [0, 0, 1], /** @id MochiKit.Color.brownColor */ brown: [0.6, 0.4, 0.2], /** @id MochiKit.Color.cyanColor */ cyan: [0, 1, 1], /** @id MochiKit.Color.darkGrayColor */ darkGray: [third, third, third], /** @id MochiKit.Color.grayColor */ gray: [0.5, 0.5, 0.5], /** @id MochiKit.Color.greenColor */ green: [0, 1, 0], /** @id MochiKit.Color.lightGrayColor */ lightGray: [2 * third, 2 * third, 2 * third], /** @id MochiKit.Color.magentaColor */ magenta: [1, 0, 1], /** @id MochiKit.Color.orangeColor */ orange: [1, 0.5, 0], /** @id MochiKit.Color.purpleColor */ purple: [0.5, 0, 0.5], /** @id MochiKit.Color.redColor */ red: [1, 0, 0], /** @id MochiKit.Color.transparentColor */ transparent: [0, 0, 0, 0], /** @id MochiKit.Color.whiteColor */ white: [1, 1, 1], /** @id MochiKit.Color.yellowColor */ yellow: [1, 1, 0] }; var makeColor = function (name, r, g, b, a) { var rval = this.fromRGB(r, g, b, a); this[name] = function () { return rval; }; return rval; }; for (var k in colors) { var name = k + "Color"; var bindArgs = m.concat( [makeColor, this.Color, name], colors[k] ); this.Color[name] = m.bind.apply(null, bindArgs); } var isColor = function () { for (var i = 0; i < arguments.length; i++) { if (!(arguments[i] instanceof MochiKit.Color.Color)) { return false; } } return true; }; var compareColor = function (a, b) { return a.compareRGB(b); }; m.nameFunctions(this); m.registerComparator(this.Color.NAME, isColor, compareColor); this.EXPORT_TAGS = { ":common": this.EXPORT, ":all": m.concat(this.EXPORT, this.EXPORT_OK) }; } }); MochiKit.Color.EXPORT = [ "Color" ]; MochiKit.Color.EXPORT_OK = [ "clampColorComponent", "rgbToHSL", "hslToRGB", "rgbToHSV", "hsvToRGB", "toColorPart" ]; MochiKit.Color.__new__(); MochiKit.Base._exportSymbols(this, MochiKit.Color); // Full table of css3 X11 colors MochiKit.Color.Color._namedColors = { aliceblue: "#f0f8ff", antiquewhite: "#faebd7", aqua: "#00ffff", aquamarine: "#7fffd4", azure: "#f0ffff", beige: "#f5f5dc", bisque: "#ffe4c4", black: "#000000", blanchedalmond: "#ffebcd", blue: "#0000ff", blueviolet: "#8a2be2", brown: "#a52a2a", burlywood: "#deb887", cadetblue: "#5f9ea0", chartreuse: "#7fff00", chocolate: "#d2691e", coral: "#ff7f50", cornflowerblue: "#6495ed", cornsilk: "#fff8dc", crimson: "#dc143c", cyan: "#00ffff", darkblue: "#00008b", darkcyan: "#008b8b", darkgoldenrod: "#b8860b", darkgray: "#a9a9a9", darkgreen: "#006400", darkgrey: "#a9a9a9", darkkhaki: "#bdb76b", darkmagenta: "#8b008b", darkolivegreen: "#556b2f", darkorange: "#ff8c00", darkorchid: "#9932cc", darkred: "#8b0000", darksalmon: "#e9967a", darkseagreen: "#8fbc8f", darkslateblue: "#483d8b", darkslategray: "#2f4f4f", darkslategrey: "#2f4f4f", darkturquoise: "#00ced1", darkviolet: "#9400d3", deeppink: "#ff1493", deepskyblue: "#00bfff", dimgray: "#696969", dimgrey: "#696969", dodgerblue: "#1e90ff", firebrick: "#b22222", floralwhite: "#fffaf0", forestgreen: "#228b22", fuchsia: "#ff00ff", gainsboro: "#dcdcdc", ghostwhite: "#f8f8ff", gold: "#ffd700", goldenrod: "#daa520", gray: "#808080", green: "#008000", greenyellow: "#adff2f", grey: "#808080", honeydew: "#f0fff0", hotpink: "#ff69b4", indianred: "#cd5c5c", indigo: "#4b0082", ivory: "#fffff0", khaki: "#f0e68c", lavender: "#e6e6fa", lavenderblush: "#fff0f5", lawngreen: "#7cfc00", lemonchiffon: "#fffacd", lightblue: "#add8e6", lightcoral: "#f08080", lightcyan: "#e0ffff", lightgoldenrodyellow: "#fafad2", lightgray: "#d3d3d3", lightgreen: "#90ee90", lightgrey: "#d3d3d3", lightpink: "#ffb6c1", lightsalmon: "#ffa07a", lightseagreen: "#20b2aa", lightskyblue: "#87cefa", lightslategray: "#778899", lightslategrey: "#778899", lightsteelblue: "#b0c4de", lightyellow: "#ffffe0", lime: "#00ff00", limegreen: "#32cd32", linen: "#faf0e6", magenta: "#ff00ff", maroon: "#800000", mediumaquamarine: "#66cdaa", mediumblue: "#0000cd", mediumorchid: "#ba55d3", mediumpurple: "#9370db", mediumseagreen: "#3cb371", mediumslateblue: "#7b68ee", mediumspringgreen: "#00fa9a", mediumturquoise: "#48d1cc", mediumvioletred: "#c71585", midnightblue: "#191970", mintcream: "#f5fffa", mistyrose: "#ffe4e1", moccasin: "#ffe4b5", navajowhite: "#ffdead", navy: "#000080", oldlace: "#fdf5e6", olive: "#808000", olivedrab: "#6b8e23", orange: "#ffa500", orangered: "#ff4500", orchid: "#da70d6", palegoldenrod: "#eee8aa", palegreen: "#98fb98", paleturquoise: "#afeeee", palevioletred: "#db7093", papayawhip: "#ffefd5", peachpuff: "#ffdab9", peru: "#cd853f", pink: "#ffc0cb", plum: "#dda0dd", powderblue: "#b0e0e6", purple: "#800080", red: "#ff0000", rosybrown: "#bc8f8f", royalblue: "#4169e1", saddlebrown: "#8b4513", salmon: "#fa8072", sandybrown: "#f4a460", seagreen: "#2e8b57", seashell: "#fff5ee", sienna: "#a0522d", silver: "#c0c0c0", skyblue: "#87ceeb", slateblue: "#6a5acd", slategray: "#708090", slategrey: "#708090", snow: "#fffafa", springgreen: "#00ff7f", steelblue: "#4682b4", tan: "#d2b48c", teal: "#008080", thistle: "#d8bfd8", tomato: "#ff6347", turquoise: "#40e0d0", violet: "#ee82ee", wheat: "#f5deb3", white: "#ffffff", whitesmoke: "#f5f5f5", yellow: "#ffff00", yellowgreen: "#9acd32" }; MochiKit-1.4.2/META.json0000660000175000017500000000055311113647640013724 0ustar scottscott{ "recommends": { "JSAN": "0.10" }, "name": "MochiKit", "license": "mit", "author": [ "Bob Ippolito " ], "abstract": "Python-inspired JavaScript kit", "generated_by": "MochiKit's build script", "build_requires": { "Test.Simple": "0.11" }, "version": "1.4.2", "provides": {} }MochiKit-1.4.2/include/0000755000175000017500000000000011136470265013727 5ustar scottscottMochiKit-1.4.2/include/css/0000755000175000017500000000000011136470265014517 5ustar scottscottMochiKit-1.4.2/include/css/general.css0000660000175000017500000000333011102215552016630 0ustar scottscottbody { font-size: 76%; color: #5C5D5F; margin: 0; font-family: Verdana, Helvetica, sans-serif; } /* ---- TYPOGRAPHY ----------------------*/ h1, h2, h3, h4, h5, h6 { margin: 0; color: #4B81BC; font-family: Trebuchet MS, verdana, sans-serif; } h1 { font-size: 2em; margin-bottom: .5em; } h1 em { color: #00C5E8; font-style: normal; background: none; } h2 { font-size: 1.4em; margin-bottom: .3em; font-weight: normal; } h3 { font-size: 1.2em; } h4 { font-size: 1.1em; font-family: Verdana, Helvetica, sans-serif; } a { color: #4b81bc; } a:hover { color: #abd038; } a.email { background: url(../../images/icon_email.gif) no-repeat left center; padding-left: 15px; } p a { font-weight: bold; } p { line-height: 1.5em; margin: 0em 0em 1em; color: #5C5D5F; } em { font-style: normal; background-color: #FFFDD4; } ul, ol { line-height: 1.5em; } ul { list-style: none; margin: 0em 0em 1em 1.8em; padding: 0; } dl { } dt { font-weight: bold; margin-bottom: .2em; color: #4B4545; } dd { margin-left: 2em; margin-bottom: 2em; } tt { font-size: 120%; } strong { color: #4b81bc; font-weight: bold; } .weak { font-size: .9em; font-weight: normal; } .contextual { font-size: .9em; color: #888; } .img { letter-spacing: -1000em; text-indent : -999em; overflow: hidden; display: block; background-repeat: repeat; background-color: transparent; /* IE FLICKER FIX - no background position! */ } /* Just for Opera, but hide from MacIE */ /*\*/html>body .img { letter-spacing : normal; text-indent : -999em; overflow : hidden;} /* End of hack */ /* ---- GENERAL ELEMENTS ----------------*/ hr { border: none; border-bottom: 1px solid #aaa; background: none; height: 1px; } a img { border: none; } .clear { clear: both; } .invisible { display: none; } MochiKit-1.4.2/include/css/documentation.css0000660000175000017500000000603211102215552020066 0ustar scottscott/************************** **** GENERAL **** ***************************/ body { font-size: 76%; color: #5C5D5F; margin: 0; font-family: Verdana, Helvetica, sans-serif; background: url("../_img/bg_docheader.gif") repeat-x; } /* ---- TYPOGRAPHY ----------------------*/ h1, h2, h3, h4, h5, h6 { margin: 0; color: #8ba726; font-family: Trebuchet MS, verdana, sans-serif; } h1 { font-size: 2em; margin-bottom: .5em; border-bottom: 1px dotted #aaaaaa; } h1 em { color: #8ba726; font-style: normal; background: none; } h1 a { color: #8ba726; } h1 a:hover { background: none; border: none; color: #8ba726; } h2 { font-size: 1.4em; margin-bottom: .3em; font-weight: normal; } h3 { font-size: 1.2em; } h4 { font-size: 1.1em; font-family: Verdana, Helvetica, sans-serif; } a { color: #8ba726; } a:hover { text-decoration: none; background: #faffe9; padding: .1; border-bottom: 1px dotted #8ba726; } a.email { background: url(../../images/icon_email.gif) no-repeat left center; padding-left: 15px; } p a { font-weight: bold; } p { line-height: 1.5em; margin: 0em 0em 1em; color: #5C5D5F; } em { font-weight: bold; background-color: transparent; } ul, ol { line-height: 1.5em; } ul { list-style: none; margin: 0em 0em 1em 1.8em; padding: 0; } dl { } dt { font-weight: bold; margin-bottom: .2em; color: #4B4545; } dd { margin-left: 2em; margin-bottom: 2em; } tt { font-size: 120%; } strong { color: #4b81bc; font-weight: bold; } .weak { font-size: .9em; font-weight: normal; } .contextual { font-size: .9em; color: #888; } #mainlink { margin-top: 34px; margin-left: 20px; } a.indexlink { float: right; font-size: 1.5em; margin-right: 2em; } div.document { margin: 0em 20px 1em; padding-top: 20px; padding-left: 10px; } div.section { margin-bottom: 2em; } a.footnote-reference { vertical-align: super; font-size: 50%; text-decoration: none; } pre.literal-block { padding: 5px; font-size: 120%; color: #1C1D1F; background: #f3f3f3; padding: 1em 2em; border-left: 3px solid #ccc; } ul.simple { list-style: none; margin: 0em 0em 1em 1.3em; padding: 0; } ul.simple li { background: url("../_img/g_bullet.gif") no-repeat left .5em; padding-left: 12px; } tt { color: #1C1D1F; } table { border: 0px; } table th { border: 0px; border-bottom: 1px solid #aaaaaa; } table td { border: 0px; } table th, table td { padding: 3px; } .img { letter-spacing: -1000em; text-indent : -999em; overflow: hidden; display: block; background-repeat: repeat; background-color: transparent; /* IE FLICKER FIX - no background position! */ } /* Just for Opera, but hide from MacIE */ /*\*/html>body .img { letter-spacing : normal; text-indent : -999em; overflow : hidden;} /* End of hack */ /* ---- GENERAL ELEMENTS ----------------*/ hr { border: none; border-bottom: 1px solid #aaa; background: none; height: 1px; } a img { border: none; text-decoration: none; } .clear { clear: both; } .invisible { display: none; } MochiKit-1.4.2/include/_img/0000755000175000017500000000000011136470265014642 5ustar scottscottMochiKit-1.4.2/include/_img/bg_docheader.gif0000660000175000017500000000642411102215552017710 0ustar scottscottGIF89a@pDT [lMrUx"}&#$#n.}Fut>8yzx~L?KH78LJn(GA(+wsj|3&66}1@=::5E-@3k49%%q"!0*0F =i EIBki CtCMGpm. K(Q@26ER(4:BN@WVUKHY*z$0P..-y#O8I/F&>TX=~&MM?<1Lv Y+I5T1C71RA);C,y#4G0x#6WI>FXu VL'ZZDSau v!9,UHOw!<9JS+Z)={%|%3w!{$QX!,@pH*L8#J谢ŋ3FƌC>8Q4(S˗+%|M rܹϟ6y HZʴiӤP"uJTCjʫׯ_ٮdY˶pmK.[x}߿: L0È +8ǐۚLrȘ3[L3ϠCFiӢS>ͺc˖=۷gލmb N\ȑ_<“HNz>سkn{K@q_Ϟ=_Aÿ7& B FhƆv!((Ŋ,").8<#9)$?Aa4P:T2OV$\vy×`)&]i&c)\*!t9'xiu橌 (j衅 6z袦D*fTj饘Z:馛f)!ꨤaꩨz*ꫩJͬJM뮹++kŎ6,[̵f vj+m1.+fǾo,k0',p\CWLq?lO% ,l&r( 0ϰ4\s8笳<Ӭ3|!йmGL#LGTbXcM\wWw5d D2hfvkǝf`v|߀{~w ',7G.W7砃o韗.쳿n."s?W_}goG#o⧯~ /oϯo6H@L` @* &H ZpȠ7 zЂ y(4(V00D gBU8̡q?ܡu"Pz&.PH&Jz8c.z]ԢHF0dL(.pH:Qxȇ>Q H?$"H?b⑐4$'IJN#-Jj(iR4(WTE$fIYᖸ̥.qY^rԥ/AbL2Lc:ә̌2IjZLȦ6Mm^8yLD v9IOw̧>~>πLBЅnD!Њ:th*юzԣRHGJR~-JI`0ifJӚڔ1KoӚP:ԟH=*Q*Ԥ:ըN*#JժV5XͪVjծRu` ƺRhE+Yֶgm\W@5xͫ^j׾{ l^J*tHb:ed Y&ಘM(6v6 -f=KZΊ6 HjSۊֺ]lgZֵU-v[ np{KVqw:шt;ZΥv],d o@׼Mz |᫉~W^,`QF0;v'La p+k FL(NUlx0N1%@(wc7wLc+HN&;JrL&[XβeDx`3Ǽ0ˇh6p:yxs">πMBЀ.Fѐ!J[ғδ/iaxZKGMjQԨtWMTzufMZֱۚεe}^zױMb6la'nAjζmk{=T憂vx7Ʒ ~xMpOŸ; W%?\wȸ7~x 9Nr!׸.V0gsۜ4W>?ЇNHїNtHTPzO@[U֡_>vhOvjo{Nw˝uW߻O~/Ư%[|/5󟟆GOz҃O}W?Ի^=!fO>Ͻm{^ A/|;O~S_ǾφH׿g Ͽ?xW d8( xx"8$8p()X,؂*(X(04X5 8:6؃>@5DXFxJKxNLJX`PVxX\؅]`^8\XephjxІnorpXnX q|؇}ᇂȇ;MochiKit-1.4.2/include/_img/g_bullet.gif0000660000175000017500000000014611102215552017112 0ustar scottscottGIF89aL@ª>!,I *UV1!X;MochiKit-1.4.2/include/_img/g_logo_doc.gif0000660000175000017500000001014111102215552017404 0ustar scottscottGIF89aeݴs|Ti Z}櫰վtotՐޛ?m)ڃ{ڝmEo[r ayH|S欺dܤ䂟Tj [ЄσM{q˪fy#Ւ_v OŽ&m.\]sx=Yo 訿Xܥ䢺œ̫쟹GvyպsoVk чzXn rDdӎrז}fy>g]jy~[oe~7ve}ay@֮zުѳxݎֆQy8iٿơ?YmWl ⳠJxNhq2s%ׯyhtkه9KOϰH3c{ؿZp ]dy`w·vT_Wǣѱbzаs5|Uj |B.x\u8k߬z Ynшij|)ٯA2ujsy!,e HVBư#8Hŋ3jȱG.OÓ(Ǘ0cʜI3# 4RpԪG,j J9x*iATFJZTҫ;5XBׯ`/ZJ6 ª]K lK7 Z9߿3i n*^mLFR)$`\@$VNHhѰ̺=QP2H<dabySڵqS^Wȝ;tJS6Pms0WA,IKE6 L/Ptp%߁5%Q\\\qdpxx{GKV5EWhs:]:.c[&4e=)S/ J`}bw:=5`BQmw'n^6 zO뭔,H4†ņܽ{ԻdB~YPR&^OƔ @^`(`I2s`֊6{_7ࡠ˟g-}fg(9/%G!~~\ 8{RQ P4w PSHfzF:C?J@~Ӏ(k d̂uu{cXWXc}ܐ ;<A~&4 9V$WvWzPp(A7'/>ĵ#@b_rm0BDV2f%T@0@VKqx#Xsp868 -#A:gQ<5!P;jSh(Q&7jK>x.`,Pj͒m q G9]kȸ3Mt.5(hAghE)kV32fs(gEy>T;ҍAJ8X30qv'uǗbl;AU {7,%$\u_4ataEЏJ8> ԵUupG4 7S{rZ0,_T`6 2 z d*aPG2))ZEu1S^)'ti0p>Io囵i(TDĴ9Թ; ^ٝ" 6jXyY @6Egr^U2dyy0<&400,Y!|,XF&=橉ox)g:"Iai'E2;AauV: CChy}"ڢy2;"y8u]:-.5%pXsO3;z2Cv8'iH:e4/2my;E`J'!/\i=caڦJ1xRD]zJ-9 v`|l{zX1P^>6ygKo⡋ci}49: "5ڪQv: ;MochiKit-1.4.2/LICENSE.txt0000660000175000017500000002406711102215706014124 0ustar scottscottMochiKit is dual-licensed software. It is available under the terms of the MIT License, or the Academic Free License version 2.1. The full text of each license is included below. MIT License =========== Copyright (c) 2005 Bob Ippolito. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. Academic Free License v. 2.1 ============================ Copyright (c) 2005 Bob Ippolito. All rights reserved. This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following notice immediately following the copyright notice for the Original Work: Licensed under the Academic Free License version 2.1 1) Grant of Copyright License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license to do the following: a) to reproduce the Original Work in copies; b) to prepare derivative works ("Derivative Works") based upon the Original Work; c) to distribute copies of the Original Work and Derivative Works to the public; d) to perform the Original Work publicly; and e) to display the Original Work publicly. 2) Grant of Patent License. Licensor hereby grants You a world-wide, royalty-free, non-exclusive, perpetual, sublicenseable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, to make, use, sell and offer for sale the Original Work and Derivative Works. 3) Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor hereby agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work, and by publishing the address of that information repository in a notice immediately following the copyright notice that applies to the Original Work. 4) Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior written permission of the Licensor. Nothing in this License shall be deemed to grant any rights to trademarks, copyrights, patents, trade secrets or any other intellectual property of Licensor except as expressly stated herein. No patent license is granted to make, use, sell or offer to sell embodiments of any patent claims other than the licensed claims defined in Section 2. No right is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under different terms from this License any Original Work that Licensor otherwise would have a right to license. 5) This section intentionally omitted. 6) Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. 7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately proceeding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to Original Work is granted hereunder except under this disclaimer. 8) Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to any person for any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to liability for death or personal injury resulting from Licensor's negligence to the extent applicable law prohibits such limitation. Some jurisdictions do not allow the exclusion or limitation of incidental or consequential damages, so this exclusion and limitation may not apply to You. 9) Acceptance and Termination. If You distribute copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. Nothing else but this License (or another written agreement between Licensor and You) grants You permission to create Derivative Works based upon the Original Work or to exercise any of the rights granted in Section 1 herein, and any attempt to do so except under the terms of this License (or another written agreement between Licensor and You) is expressly prohibited by U.S. copyright law, the equivalent laws of other countries, and by international treaty. Therefore, by exercising any of the rights granted to You in Section 1 herein, You indicate Your acceptance of this License and all of its terms and conditions. 10) Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. 11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of the U.S. Copyright Act, 17 U.S.C. § 101 et seq., the equivalent laws of other countries, and international treaty. This section shall survive the termination of this License. 12) Attorneys Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. 13) Miscellaneous. This License represents the complete agreement concerning the subject matter hereof. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. 14) Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. 15) Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. This license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved. Permission is hereby granted to copy and distribute this license without modification. This license may not be modified without the express written permission of its copyright owner.