Index: openacs-4/packages/ajaxhelper/ajaxhelper.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/ajaxhelper.info,v diff -u -r1.3 -r1.4 --- openacs-4/packages/ajaxhelper/ajaxhelper.info 5 Apr 2006 06:38:41 -0000 1.3 +++ openacs-4/packages/ajaxhelper/ajaxhelper.info 20 Apr 2006 12:31:27 -0000 1.4 @@ -8,13 +8,13 @@ t ajax - + Hamilton Chua - Provides helper procs to generate javascript for Ajax and cinematic effects. - Solutiongrove + Provides helper procs to generate javascript for Ajax and cinematic effects. Include Scriptaculous (1.6.1) Javascript Libraries and the Yahoo UI Libraries. + Solution Grove 0 - + Index: openacs-4/packages/ajaxhelper/www/doc/index.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/doc/index.html,v diff -u -r1.2 -r1.3 --- openacs-4/packages/ajaxhelper/www/doc/index.html 5 Apr 2006 06:38:42 -0000 1.2 +++ openacs-4/packages/ajaxhelper/www/doc/index.html 20 Apr 2006 12:31:27 -0000 1.3 @@ -53,7 +53,7 @@     @ah_sources;noquote@

Compiled Template:
-
<script<script type="text/javascript" src="/ajax/prototype/prototype.js"></script> 
<scriptscript>
<script type="text/javascript" src="/ajax/scriptaculous/slider.js"></script>
-
<scriptscript>
<script type="text/javascript" src="/ajax/scriptaculous/scriptaculous.js"></script>

The above TCL API generates the default sources that must be declared for you to be able to use the javascript -effects. Ajax Helper has support for overlibmws (DHTML callouts) and -RICO (other cinematic effects) in addition to scriptaculous.
+libraries Ajax Helper has support for overlibmws (DHTML callouts) and +RICO (other cinematic effects) in addition to scriptaculous.  +Scriptaculous is the default javascript library.

To generate the javascript sources for Rico :

@@ -97,7 +97,7 @@
NOTE :

-You can combine sources by doing something like this
+You can combine sources by doing this

    set ah_sources [ah::js_sources -default]
    append ah_sources [ah::js_sources -source @@ -112,29 +112,140 @@
Ajax Procedures :

-
Scriptaculous has a pair of javascript functions that alllow +Prototype has a pair of javascript functions that alllow programmers to use XMLHTTP. The ajax.updater and ajax.request functions. See http://wiki.script.aculo.us/scriptaculous/show/Ajax.Updater and http://wiki.script.aculo.us/scriptaculous/show/Ajax.Request -for more informaiton about the scriptaculous functions.
+for more information about these javascript functions.

The TCL API is used like this

-    set request [ah::ajaxrequest -url "/url/to/call" --pars "parameter1=parameter_value&parameter1=parameter_value" --options "asynchronous:true" ]
+    set request [ah::ajaxrequest -url +"/url/to/call"  +\
+            +            +            +            +     -pars +"parameter1=parameter_value&parameter1=parameter_value"  ]

The above api will generate an ajax.request javascript function that is -best placed in a javascript event.
+best placed in an  event like "onClick".

    <a href="#" onClick="@request;noquote@">

+Consult the api-doc for more information about other parameters you can +pass on to the ah::ajaxrequest proc.

+The ah::ajaxrequest will make an xmlhttp call but does not do anything +about the response. To update content based on the response from an +xmlhttp request, use ah::ajaxupdate. This procedure will not only make +an xmlhttp call but update the contents of a div or layer with the +response text of the xmlhttp request.

+Here's an example :

+       set js_update_connections +[ah::ajaxupdate -container "connections"  \
+            +    -url "/url/to/call" \
+            +    -enclose  \
+            +    -pars +"'effects=$effects&limit_n=$limit_n'"  \
+                +-effect "Fade" \
+            +    -effectopts "duration: 0.5"]

-
+On the adp side, you can just put
+
+      @js_update_connections;noquote@
+
+The "-enclose" parameter tells the procedure to enclose the resulting +script in script tags <script></script>. This is another +option in addition to putting the scripts in html event attributes like +onClick, onMouseover or onChange.
+
+The "-pars" parameter is where you pass the querystring that you want +to send along with the xmlhttp request. Notice that it takes the form +of a querystring that you normally see in the address bar of your +browser. Use this to pass values to the URL you are making an xmlhttp +request to.
+
+The "-effect" parameter is an optional parameter that allows you to +specify the effect you want to execute after the container's content +has been updated.
+
+Cinematic Effects :
+
+
Use ah::effects to generate javascript that allows you to +implement transitional and cinematic effects to html elements. You will +need to consult the scriptaculous documentation +http://wiki.script.aculo.us/scriptaculous/tags/effects to know what +kinds of +effects and what kinds of options you can pass to the effect script.
+
+The procedure is called in this manner :
+
+    set effect [ah::effect -element "container"
+            +            +               +-effect "Fade"
+            +            +        +       -options "duration: 1.5"]
+NOTE :
+The Effect name and the options are case sensitive.
+
+

+DHTML Callouts :
+
+
There is currently basic support for overlibmws. Right now we +are able to create bubble type call outs.
+
+In your tcl file ...
+
+   set onmouseover [ah::bubblecallout -text " Contents of My +Popup" ]
+
+The adp file should have something like this ....
+  
+   <a href="#" @onmouseover;noquote@ >Link with +Popup</a>
+
+Drag and Drop Sortables :
+
+
Sortables are documented in the scriptaculous wiki http://wiki.script.aculo.us/scriptaculous/show/Sortables.
+For sortables to work you will need to define a container which will +hold the elements you want to be sortable.
+
+Here is what the script looks like
+
+    append scripts [ah::sortable -element "container"
+            +            +            +            +     -options +"tag:'div',only:'portlet',overlap:'horizontal',constraint:false,ghosting:false"]
+
+You adp page should contain a div with id attribute container. This +"container" should have subcontainers which the above script will make +sortable.
+
+
+

+
+
+
+
- + \ No newline at end of file Index: openacs-4/packages/ajaxhelper/www/prototype/prototype.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/prototype/Attic/prototype.js,v diff -u -r1.2 -r1.3 --- openacs-4/packages/ajaxhelper/www/prototype/prototype.js 31 Mar 2006 08:15:36 -0000 1.2 +++ openacs-4/packages/ajaxhelper/www/prototype/prototype.js 20 Apr 2006 12:31:28 -0000 1.3 @@ -1,4 +1,4 @@ -/* Prototype JavaScript framework, version 1.5.0_pre1 +/* Prototype JavaScript framework, version 1.5.0_rc0 * (c) 2005 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. @@ -7,7 +7,7 @@ /*--------------------------------------------------------------------------*/ var Prototype = { - Version: '1.5.0_pre1', + Version: '1.5.0_rc0', ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, @@ -25,7 +25,7 @@ var Abstract = new Object(); Object.extend = function(destination, source) { - for (property in source) { + for (var property in source) { destination[property] = source[property]; } return destination; @@ -176,7 +176,7 @@ }, evalScripts: function() { - return this.extractScripts().map(eval); + return this.extractScripts().map(function(script) { return eval(script) }); }, escapeHTML: function() { @@ -355,7 +355,7 @@ var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); - if (value >= (result || value)) + if (result == undefined || value >= result) result = value; }); return result; @@ -365,7 +365,7 @@ var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); - if (value <= (result || value)) + if (result == undefined || value < result) result = value; }); return result; @@ -447,7 +447,8 @@ Object.extend(Array.prototype, Enumerable); -Array.prototype._reverse = Array.prototype.reverse; +if (!Array.prototype._reverse) + Array.prototype._reverse = Array.prototype.reverse; Object.extend(Array.prototype, { _each: function(iterator) { @@ -476,7 +477,7 @@ flatten: function() { return this.inject([], function(array, value) { - return array.concat(value.constructor == Array ? + return array.concat(value && value.constructor == Array ? value.flatten() : [value]); }); }, @@ -498,21 +499,13 @@ return (inline !== false ? this : this.toArray())._reverse(); }, - shift: function() { - var result = this[0]; - for (var i = 0; i < this.length - 1; i++) - this[i] = this[i + 1]; - this.length--; - return result; - }, - inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; } }); var Hash = { _each: function(iterator) { - for (key in this) { + for (var key in this) { var value = this[key]; if (typeof value == 'function') continue; @@ -590,9 +583,9 @@ var Ajax = { getTransport: function() { return Try.these( + function() {return new XMLHttpRequest()}, function() {return new ActiveXObject('Msxml2.XMLHTTP')}, - function() {return new ActiveXObject('Microsoft.XMLHTTP')}, - function() {return new XMLHttpRequest()} + function() {return new ActiveXObject('Microsoft.XMLHTTP')} ) || false; }, @@ -644,6 +637,7 @@ this.options = { method: 'post', asynchronous: true, + contentType: 'application/x-www-form-urlencoded', parameters: '' } Object.extend(this.options, options || {}); @@ -707,8 +701,7 @@ 'Accept', 'text/javascript, text/html, application/xml, text/xml, */*']; if (this.options.method == 'post') { - requestHeaders.push('Content-type', - 'application/x-www-form-urlencoded'); + requestHeaders.push('Content-type', this.options.contentType); /* Force "Connection: close" for Mozilla browsers to work around * a bug where XMLHttpReqeuest sends an incorrect Content-length @@ -739,7 +732,7 @@ evalJSON: function() { try { - return eval(this.header('X-JSON')); + return eval('(' + this.header('X-JSON') + ')'); } catch (e) {} }, @@ -900,20 +893,29 @@ Element.extend = function(element) { if (!element) return; + if (_nativeExtensions) return element; if (!element._extended && element.tagName && element != window) { - var methods = Element.Methods; + var methods = Element.Methods, cache = Element.extend.cache; for (property in methods) { var value = methods[property]; if (typeof value == 'function') - element[property] = value.bind(null, element); + element[property] = cache.findOrStore(value); } } element._extended = true; return element; } +Element.extend.cache = { + findOrStore: function(value) { + return this[value] = this[value] || function() { + return value.apply(null, [this].concat($A(arguments))); + } + } +} + Element.Methods = { visible: function(element) { return $(element).style.display != 'none'; @@ -1035,7 +1037,7 @@ setStyle: function(element, style) { element = $(element); - for (name in style) + for (var name in style) element.style[name.camelize()] = style[name]; }, @@ -1105,6 +1107,29 @@ Object.extend(Element, Element.Methods); +var _nativeExtensions = false; + +if(!HTMLElement && /Konqueror|Safari|KHTML/.test(navigator.userAgent)) { + var HTMLElement = {} + HTMLElement.prototype = document.createElement('div').__proto__; +} + +Element.addMethods = function(methods) { + Object.extend(Element.Methods, methods || {}); + + if(typeof HTMLElement != 'undefined') { + var methods = Element.Methods, cache = Element.extend.cache; + for (property in methods) { + var value = methods[property]; + if (typeof value == 'function') + HTMLElement.prototype[property] = cache.findOrStore(value); + } + _nativeExtensions = true; + } +} + +Element.addMethods(); + var Toggle = new Object(); Toggle.display = Element.toggle; @@ -1123,7 +1148,8 @@ try { this.element.insertAdjacentHTML(this.adjacency, this.content); } catch (e) { - if (this.element.tagName.toLowerCase() == 'tbody') { + var tagName = this.element.tagName.toLowerCase(); + if (tagName == 'tbody' || tagName == 'tr') { this.insertContent(this.contentFromAnonymousTable()); } else { throw e; @@ -1396,7 +1422,7 @@ form = $(form); var elements = new Array(); - for (tagName in Form.Element.Serializers) { + for (var tagName in Form.Element.Serializers) { var tagElements = form.getElementsByTagName(tagName); for (var j = 0; j < tagElements.length; j++) elements.push(tagElements[j]); @@ -1518,23 +1544,17 @@ var value = '', opt, index = element.selectedIndex; if (index >= 0) { opt = element.options[index]; - value = opt.value; - if (!value && !('value' in opt)) - value = opt.text; + value = opt.value || opt.text; } return [element.name, value]; }, selectMany: function(element) { - var value = new Array(); + var value = []; for (var i = 0; i < element.length; i++) { var opt = element.options[i]; - if (opt.selected) { - var optValue = opt.value; - if (!optValue && !('value' in opt)) - optValue = opt.text; - value.push(optValue); - } + if (opt.selected) + value.push(opt.value || opt.text); } return [element.name, value]; } @@ -1751,7 +1771,8 @@ }); /* prevent memory leaks in IE */ -Event.observe(window, 'unload', Event.unloadCache, false); +if (navigator.appVersion.match(/\bMSIE\b/)) + Event.observe(window, 'unload', Event.unloadCache, false); var Position = { // set to true if needed, warning: firefox performance problems // NOT neeeded for page scrolling, only if draggable contained in Index: openacs-4/packages/ajaxhelper/www/scriptaculous/dragdrop.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/scriptaculous/Attic/dragdrop.js,v diff -u -r1.2 -r1.3 --- openacs-4/packages/ajaxhelper/www/scriptaculous/dragdrop.js 31 Mar 2006 08:15:36 -0000 1.2 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/dragdrop.js 20 Apr 2006 12:31:28 -0000 1.3 @@ -1,4 +1,5 @@ // Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz) // // See scriptaculous.js for full license. @@ -15,7 +16,8 @@ element = $(element); var options = Object.extend({ greedy: true, - hoverclass: null + hoverclass: null, + tree: false }, arguments[1] || {}); // cache containers @@ -37,12 +39,27 @@ this.drops.push(options); }, + + findDeepestChild: function(drops) { + deepest = drops[0]; + + for (i = 1; i < drops.length; ++i) + if (Element.isParent(drops[i].element, deepest.element)) + deepest = drops[i]; + + return deepest; + }, isContained: function(element, drop) { - var parentNode = element.parentNode; - return drop._containers.detect(function(c) { return parentNode == c }); + var containmentNode; + if(drop.tree) { + containmentNode = element.treeNode; + } else { + containmentNode = element.parentNode; + } + return drop._containers.detect(function(c) { return containmentNode == c }); }, - + isAffected: function(point, element, drop) { return ( (drop.element!=element) && @@ -68,18 +85,22 @@ show: function(point, element) { if(!this.drops.length) return; + var affected = []; if(this.last_active) this.deactivate(this.last_active); this.drops.each( function(drop) { - if(Droppables.isAffected(point, element, drop)) { - if(drop.onHover) - drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); - if(drop.greedy) { - Droppables.activate(drop); - throw $break; - } - } + if(Droppables.isAffected(point, element, drop)) + affected.push(drop); }); + + if(affected.length>0) { + drop = Droppables.findDeepestChild(affected); + Position.within(drop.element, point[0], point[1]); + if(drop.onHover) + drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element)); + + Droppables.activate(drop); + } }, fire: function(event, element) { @@ -187,15 +208,17 @@ initialize: function(element) { var options = Object.extend({ handle: false, - starteffect: function(element) { - new Effect.Opacity(element, {duration:0.2, from:1.0, to:0.7}); + starteffect: function(element) { + element._opacity = Element.getOpacity(element); + new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7}); }, reverteffect: function(element, top_offset, left_offset) { var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur}); }, - endeffect: function(element) { - new Effect.Opacity(element, {duration:0.2, from:0.7, to:1.0}); + endeffect: function(element) { + var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0 + new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity}); }, zindex: 1000, revert: false, @@ -207,8 +230,10 @@ this.element = $(element); - if(options.handle && (typeof options.handle == 'string')) - this.handle = Element.childrenWithClassName(this.element, options.handle, true)[0]; + if(options.handle && (typeof options.handle == 'string')) { + var h = Element.childrenWithClassName(this.element, options.handle, true); + if(h.length>0) this.handle = h[0]; + } if(!this.handle) this.handle = $(options.handle); if(!this.handle) this.handle = this.element; @@ -389,7 +414,7 @@ if(this.options.snap) { if(typeof this.options.snap == 'function') { - p = this.options.snap(p[0],p[1]); + p = this.options.snap(p[0],p[1],this); } else { if(this.options.snap instanceof Array) { p = p.map( function(v, i) { @@ -412,6 +437,7 @@ if(this.scrollInterval) { clearInterval(this.scrollInterval); this.scrollInterval = null; + Draggables._lastScrollPointer = null; } }, @@ -440,7 +466,14 @@ Position.prepare(); Droppables.show(Draggables._lastPointer, this.element); Draggables.notify('onDrag', this); - this.draw(Draggables._lastPointer); + Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer); + Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000; + Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000; + if (Draggables._lastScrollPointer[0] < 0) + Draggables._lastScrollPointer[0] = 0; + if (Draggables._lastScrollPointer[1] < 0) + Draggables._lastScrollPointer[1] = 0; + this.draw(Draggables._lastScrollPointer); if(this.options.change) this.options.change(this); }, @@ -492,30 +525,41 @@ } var Sortable = { - sortables: new Array(), + sortables: {}, - options: function(element){ - element = $(element); - return this.sortables.detect(function(s) { return s.element == element }); + _findRootElement: function(element) { + while (element.tagName != "BODY") { + if(element.id && Sortable.sortables[element.id]) return element; + element = element.parentNode; + } }, + + options: function(element) { + element = Sortable._findRootElement($(element)); + if(!element) return; + return Sortable.sortables[element.id]; + }, destroy: function(element){ - element = $(element); - this.sortables.findAll(function(s) { return s.element == element }).each(function(s){ + var s = Sortable.options(element); + + if(s) { Draggables.removeObserver(s.element); s.droppables.each(function(d){ Droppables.remove(d) }); s.draggables.invoke('destroy'); - }); - this.sortables = this.sortables.reject(function(s) { return s.element == element }); + + delete Sortable.sortables[s.element.id]; + } }, - + create: function(element) { element = $(element); var options = Object.extend({ element: element, tag: 'li', // assumes li children, override with tag: 'tagname' dropOnEmpty: false, - tree: false, // fixme: unimplemented + tree: false, + treeTag: 'ul', overlap: 'vertical', // one of 'vertical', 'horizontal' constraint: 'vertical', // one of 'vertical', 'horizontal', false containment: element, // also takes array of elements (or id's); or false @@ -565,23 +609,28 @@ var options_for_droppable = { overlap: options.overlap, containment: options.containment, + tree: options.tree, hoverclass: options.hoverclass, - onHover: Sortable.onHover, - greedy: !options.dropOnEmpty + onHover: Sortable.onHover + //greedy: !options.dropOnEmpty } + + var options_for_tree = { + onHover: Sortable.onEmptyHover, + overlap: options.overlap, + containment: options.containment, + hoverclass: options.hoverclass + } // fix for gecko engine Element.cleanWhitespace(element); options.draggables = []; options.droppables = []; - // make it so - // drop on empty handling - if(options.dropOnEmpty) { - Droppables.add(element, - {containment: options.containment, onHover: Sortable.onEmptyHover, greedy: false}); + if(options.dropOnEmpty || options.tree) { + Droppables.add(element, options_for_tree); options.droppables.push(element); } @@ -592,11 +641,20 @@ options.draggables.push( new Draggable(e, Object.extend(options_for_draggable, { handle: handle }))); Droppables.add(e, options_for_droppable); + if(options.tree) e.treeNode = element; options.droppables.push(e); }); + + if(options.tree) { + (Sortable.findTreeElements(element, options) || []).each( function(e) { + Droppables.add(e, options_for_tree); + e.treeNode = element; + options.droppables.push(e); + }); + } // keep reference - this.sortables.push(options); + this.sortables[element.id] = options; // for onupdate Draggables.addObserver(new SortableObserver(element, options.onUpdate)); @@ -605,24 +663,21 @@ // return all suitable-for-sortable elements in a guaranteed order findElements: function(element, options) { - if(!element.hasChildNodes()) return null; - var elements = []; - var only = options.only ? [options.only].flatten() : null; - $A(element.childNodes).each( function(e) { - if(e.tagName && e.tagName.toUpperCase()==options.tag.toUpperCase() && - (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) - elements.push(e); - if(options.tree) { - var grandchildren = this.findElements(e, options); - if(grandchildren) elements.push(grandchildren); - } - }); - - return (elements.length>0 ? elements.flatten() : null); + return Element.findChildren( + element, options.only, options.tree ? true : false, options.tag); }, + + findTreeElements: function(element, options) { + return Element.findChildren( + element, options.only, options.tree ? true : false, options.treeTag); + }, onHover: function(element, dropon, overlap) { - if(overlap>0.5) { + if(Element.isParent(dropon, element)) return; + + if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) { + return; + } else if(overlap>0.5) { Sortable.mark(dropon, 'before'); if(dropon.previousSibling != element) { var oldParentNode = element.parentNode; @@ -645,13 +700,37 @@ } } }, - - onEmptyHover: function(element, dropon) { - if(element.parentNode!=dropon) { - var oldParentNode = element.parentNode; - dropon.appendChild(element); + + onEmptyHover: function(element, dropon, overlap) { + var oldParentNode = element.parentNode; + var droponOptions = Sortable.options(dropon); + + if(!Element.isParent(dropon, element)) { + var index; + + var children = Sortable.findElements(dropon, {tag: droponOptions.tag}); + var child = null; + + if(children) { + var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap); + + for (index = 0; index < children.length; index += 1) { + if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) { + offset -= Element.offsetSize (children[index], droponOptions.overlap); + } else if (offset - (Element.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); + Sortable.options(oldParentNode).onChange(element); - Sortable.options(dropon).onChange(element); + droponOptions.onChange(element); } }, @@ -683,7 +762,76 @@ Element.show(Sortable._marker); }, + + _tree: function(element, options, parent) { + var children = Sortable.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: new Array, + position: parent.children.length, + container: Sortable._findChildrenElement(children[i], options.treeTag.toUpperCase()) + } + + /* Get the element containing the children and recurse over it */ + if (child.container) + this._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) + for (var i = 0; i < element.childNodes.length; ++i) + if (element.childNodes[i].tagName == containerTag) + return element.childNodes[i]; + + return null; + }, + + tree: function(element) { + element = $(element); + var sortableOptions = this.options(element); + var options = Object.extend({ + tag: sortableOptions.tag, + treeTag: sortableOptions.treeTag, + only: sortableOptions.only, + name: element.id, + format: sortableOptions.format + }, arguments[1] || {}); + + var root = { + id: null, + parent: null, + children: new Array, + container: element, + position: 0 + } + + return Sortable._tree (element, options, root); + }, + + /* 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; + }, + sequence: function(element) { element = $(element); var options = Object.extend(this.options(element), arguments[1] || {}); @@ -705,20 +853,63 @@ }); new_sequence.each(function(ident) { - var n = nodeMap[ident]; - if (n) { - n[1].appendChild(n[0]); - delete nodeMap[ident]; - } + var n = nodeMap[ident]; + if (n) { + n[1].appendChild(n[0]); + delete nodeMap[ident]; + } }); }, - + serialize: function(element) { element = $(element); + var options = Object.extend(Sortable.options(element), arguments[1] || {}); var name = encodeURIComponent( (arguments[1] && arguments[1].name) ? arguments[1].name : element.id); - return Sortable.sequence(element, arguments[1]).map( function(item) { - return name + "[]=" + encodeURIComponent(item); - }).join('&'); + + if (options.tree) { + return Sortable.tree(element, arguments[1]).children.map( function (item) { + return [name + Sortable._constructIndex(item) + "=" + + encodeURIComponent(item.id)].concat(item.children.map(arguments.callee)); + }).flatten().join('&'); + } else { + return Sortable.sequence(element, arguments[1]).map( function(item) { + return name + "[]=" + encodeURIComponent(item); + }).join('&'); + } } } + +/* Returns true if child is contained within element */ +Element.isParent = function(child, element) { + if (!child.parentNode || child == element) return false; + + if (child.parentNode == element) return true; + + return Element.isParent(child.parentNode, element); +} + +Element.findChildren = function(element, only, recursive, tagName) { + if(!element.hasChildNodes()) return null; + tagName = tagName.toUpperCase(); + if(only) only = [only].flatten(); + var elements = []; + $A(element.childNodes).each( function(e) { + if(e.tagName && e.tagName.toUpperCase()==tagName && + (!only || (Element.classNames(e).detect(function(v) { return only.include(v) })))) + elements.push(e); + if(recursive) { + var grandchildren = Element.findChildren(e, only, recursive, tagName); + if(grandchildren) elements.push(grandchildren); + } + }); + + return (elements.length>0 ? elements.flatten() : []); +} + +Element.offsetSize = function (element, type) { + if (type == 'vertical' || type == 'height') + return element.offsetHeight; + else + return element.offsetWidth; +} \ No newline at end of file Index: openacs-4/packages/ajaxhelper/www/scriptaculous/effects.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/scriptaculous/Attic/effects.js,v diff -u -r1.2 -r1.3 --- openacs-4/packages/ajaxhelper/www/scriptaculous/effects.js 31 Mar 2006 08:15:36 -0000 1.2 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/effects.js 20 Apr 2006 12:31:28 -0000 1.3 @@ -77,9 +77,12 @@ } Element.childrenWithClassName = function(element, className, findFirst) { - return [$A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { - return c.className ? Element.hasClassName(c, className) : false; - })].flatten(); + var classNameRegExp = new RegExp("(^|\\s)" + className + "(\\s|$)"); + var results = $A($(element).getElementsByTagName('*'))[findFirst ? 'detect' : 'select']( function(c) { + return (c.className && c.className.match(classNameRegExp)); + }); + if(!results) results = []; + return results; } Element.forceRerendering = function(element) { @@ -91,11 +94,6 @@ } catch(e) { } }; -['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', - 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( - function(f) { Element.Methods[f] = Element[f]; } -); - /*--------------------------------------------------------------------------*/ Array.prototype.call = function() { @@ -703,7 +701,7 @@ return new Effect.Scale(element, 100, Object.extend({ scaleContent: false, scaleX: false, - scaleFrom: 0, + scaleFrom: window.opera ? 0 : 1, scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, restoreAfterFinish: true, afterSetup: function(effect) { @@ -736,7 +734,7 @@ element = $(element); element.cleanWhitespace(); var oldInnerBottom = $(element.firstChild).getStyle('bottom'); - return new Effect.Scale(element, 0, + return new Effect.Scale(element, window.opera ? 0 : 1, Object.extend({ scaleContent: false, scaleX: false, scaleMode: 'box', @@ -943,11 +941,18 @@ effect.element.setStyle(oldStyle); } }); }}, arguments[1] || {})); -} +}; +['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', + 'collectTextNodes','collectTextNodesIgnoreClass','childrenWithClassName'].each( + function(f) { Element.Methods[f] = Element[f]; } +); + Element.Methods.visualEffect = function(element, effect, options) { s = effect.gsub(/_/, '-').camelize(); effect_class = s.charAt(0).toUpperCase() + s.substring(1); new Effect[effect_class](element, options); return $(element); -}; \ No newline at end of file +}; + +Element.addMethods(); \ No newline at end of file Index: openacs-4/packages/ajaxhelper/www/scriptaculous/scriptaculous.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/scriptaculous/Attic/scriptaculous.js,v diff -u -r1.2 -r1.3 --- openacs-4/packages/ajaxhelper/www/scriptaculous/scriptaculous.js 31 Mar 2006 08:15:36 -0000 1.2 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/scriptaculous.js 20 Apr 2006 12:31:28 -0000 1.3 @@ -20,7 +20,7 @@ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. var Scriptaculous = { - Version: '1.6', + Version: '1.6.1', require: function(libraryName) { // inserting via DOM fails in Safari 2.0, so brute force approach document.write(''); Index: openacs-4/packages/ajaxhelper/www/scriptaculous/unittest.js =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/ajaxhelper/www/scriptaculous/Attic/unittest.js,v diff -u -r1.2 -r1.3 --- openacs-4/packages/ajaxhelper/www/scriptaculous/unittest.js 31 Mar 2006 08:15:36 -0000 1.2 +++ openacs-4/packages/ajaxhelper/www/scriptaculous/unittest.js 20 Apr 2006 12:31:28 -0000 1.3 @@ -258,6 +258,9 @@ this.failures++; this.messages.push("Failure: " + message); }, + info: function(message) { + this.messages.push("Info: " + message); + }, error: function(error) { this.errors++; this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")"); @@ -336,6 +339,14 @@ }, assertVisible: function(element) { this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1])); + }, + benchmark: function(operation, iterations) { + var startAt = new Date(); + (iterations || 1).times(operation); + var timeTaken = ((new Date())-startAt); + this.info((arguments[2] || 'Operation') + ' finished ' + + iterations + ' iterations in ' + (timeTaken/1000)+'s' ); + return timeTaken; } }